#}
Deploy API on VPS WITH Traefik and Let's Encrypt SSL
Deploy GEMVC API on VPS with Traefik and Let's Encrypt SSL
VPS Deployment with Traefik & Automatic SSL
Complete guide for deploying a Dockerized GEMVC application on a VPS with Traefik reverse proxy and automatic Let's Encrypt SSL.
Docker
OpenSwoole
Traefik
Let's Encrypt
Core Concepts
- VPS: Your private server space on the internet
- Docker: Package your app into portable containers
- Traefik: Reverse proxy that auto-discovers containers
- Let's Encrypt: Free automatic SSL certificates
Part 1: Initial Server Setup
Prerequisites
- β VPS running Ubuntu 24.04 (or similar)
- β Registered domain name
- β DNS A record pointing to your VPS IP
Step 1: Install Docker
Install Docker
# Update package lists
sudo apt-get update
# Install prerequisites
sudo apt-get install -y ca-certificates curl
# Add Docker's GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Part 2: Traefik Setup
Step 2: Create Directory Structure
Create Directories
# Create infrastructure directory
mkdir -p /root/stacks/infra
cd /root/stacks/infra
Step 3: Create Traefik Docker Compose
Create /root/stacks/infra/docker-compose.yml:
docker-compose.yml (Traefik)
version: '3.8'
services:
traefik:
image: "traefik:v3.0"
container_name: "traefik"
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.email=your-email@example.com"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- shared-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.your-domain.com`)"
- "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
- "traefik.http.routers.traefik-dashboard.tls.certresolver=mytlschallenge"
- "traefik.http.routers.traefik-dashboard.service=api@internal"
networks:
shared-net:
name: shared-net
Tip: Replace your-email@example.com and your-domain.com with your actual values!
Step 4: Start Traefik
Start Traefik
cd /root/stacks/infra
docker compose up -d
Part 3: Deploy Your Application
Step 5: Create App Directory
Create App Directory
mkdir -p /root/stacks/app/gemvc-api
cd /root/stacks/app/gemvc-api
Step 6: Application Docker Compose
docker-compose.yml (App)
version: '3.8'
services:
gemvc-api:
image: your-dockerhub-username/gemvc-api:latest
container_name: gemvc-api
restart: unless-stopped
env_file:
- .env
networks:
- shared-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.gemvc-api.rule=Host(`api.your-domain.com`)"
- "traefik.http.routers.gemvc-api.entrypoints=websecure"
- "traefik.http.routers.gemvc-api.tls.certresolver=mytlschallenge"
- "traefik.http.services.gemvc-api.loadbalancer.server.port=9501"
networks:
shared-net:
external: true
Step 7: Create Environment File
info: This step is mandatory! Your application will fail without a properly configured .env file.
.env (Production)
# /root/stacks/app/gemvc-api/.env
APP_ENV=production
SWOOLE_DISPLAY_ERRORS=0
DB_HOST=your-db-host
DB_NAME=gemvc_production
DB_USER=gemvc
DB_PASSWORD=your-strong-password
TOKEN_SECRET=your-very-long-random-secret-key-minimum-32-chars
TOKEN_ISSUER=YourCompany
Secure .env
# Set strict permissions
chmod 600 /root/stacks/app/gemvc-api/.env
Step 8: Start Application
Start Application
cd /root/stacks/app/gemvc-api
docker compose up -d
Part 4: CI/CD with GitHub Actions
Step 9: GitHub Actions Workflow
GitHub Actions Workflow
# .github/workflows/docker-publish.yml
name: CI - Build and Push Docker Image
on:
release:
types: [published]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: docker/setup-buildx-action@v2
- uses: docker/login-action@v2
with:
username: \${{ secrets.DOCKERHUB_USERNAME }}
password: \${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
\${{ secrets.DOCKERHUB_USERNAME }}/gemvc-api:latest
\${{ secrets.DOCKERHUB_USERNAME }}/gemvc-api:\${{ github.ref_name }}
Step 10: Update Script
Update Script
#!/bin/bash
# /root/scripts/restart_gemvc-api.sh
set -e
APP_DIR="/root/stacks/app/gemvc-api"
echo "--- Stopping stack... ---"
cd "$APP_DIR" && docker compose down
echo "--- Pulling latest image... ---"
cd "$APP_DIR" && docker compose pull
echo "--- Starting stack... ---"
cd "$APP_DIR" && docker compose up -d
echo "--- Done! ---"
docker ps --filter "name=gemvc-api"
Make Executable
chmod +x /root/scripts/restart_gemvc-api.sh
Deployment Checklist
- DNS A record points to VPS IP
- Docker and Docker Compose installed
- Traefik running and SSL working
- .env file created with production settings
- Application container running