diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 79f7c81..4a6d343 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -73,29 +73,15 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 - - - name: Setup SSH - uses: webfactory/ssh-agent@v0.5.3 - with: - ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }} - - - name: Add host - run: | - ssh-keyscan zenful.cloud > ~/.ssh/known_hosts - - - name: Set up Docker Compose + - name: create env file run: | - # Install Docker Compose - curl -L "https://github.com/docker/compose/releases/download/v2.19.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - chmod +x /usr/local/bin/docker-compose - - - name: Copy over password - run: | - ssh deploytest@zenful.cloud "echo ${{ secrets.DB_PASSWORD }} > /home/deploytest/db-password.txt" - - - name: Run Docker Compose - run: | - export GIT_COMMIT_HASH=${{ needs.commit-hash.outputs.commit_hash }} - export DB_PASSWORD_PATH="/home/deploytest/db-password.txt" - export DOCKER_HOST=ssh://deploytest@zenful.cloud - docker-compose -f ./compose.prod.yaml up -d + echo "GIT_COMMIT_HASH=${{ github.sha }}" >> env + - name: 'Docker Stack Deploy' + uses: cssnr/stack-deploy-action@v1 + with: + name: 'guestbook' + file: 'stack.yaml' + host: zenful.cloud + user: deploy + ssh_key: ${{ secrets.DEPLOY_SSH_KEY }} + env_file: './env' diff --git a/docker-stack.yaml b/docker-stack.yaml new file mode 100644 index 0000000..34e4ce0 --- /dev/null +++ b/docker-stack.yaml @@ -0,0 +1,87 @@ +services: + reverse-proxy: + image: traefik:v3.1 + command: + - "--providers.docker" + - "--providers.docker.exposedbydefault=false" + - "--entryPoints.websecure.address=:443" + - "--certificatesresolvers.myresolver.acme.tlschallenge=true" + - "--certificatesresolvers.myresolver.acme.email=elliott@zenful.cloud" + - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + - "--entrypoints.web.address=:80" + - "--entrypoints.web.http.redirections.entrypoint.to=websecure" + - "--entrypoints.web.http.redirections.entrypoint.scheme=https" + ports: + - mode: host + protocol: tcp + published: 80 + target: 80 + - mode: host + protocol: tcp + published: 443 + target: 443 + volumes: + - letsencrypt:/letsencrypt + - /var/run/docker.sock:/var/run/docker.sock + guestbook: + image: ghcr.io/dreamsofcode-io/guestbook:${GIT_COMMIT_HASH:-prod} + labels: + - "traefik.enable=true" + - "traefik.http.middlewares.guestbook-ratelimit.ratelimit.average=20" + - "traefik.http.routers.guestbook.rule=Host(`zenful.cloud`) && !Method(`POST`)" + - "traefik.http.services.guestbook.loadbalancer.server.port=8080" + - "traefik.http.routers.guestbook.entrypoints=websecure" + - "traefik.http.routers.guestbook.tls.certresolver=myresolver" + - "traefik.http.routers.guestbook.middlewares=guestbook-ratelimit" + # Define separate router for POST methods + - "traefik.http.middlewares.guestbook-ratelimit-post.ratelimit.average=1" + - "traefik.http.middlewares.guestbook-ratelimit-post.ratelimit.period=1m" + - "traefik.http.routers.guestbook-post.rule=Host(`zenful.cloud`) && Method(`POST`)" + - "traefik.http.routers.guestbook-post.middlewares=guestbook-ratelimit-post" + - "traefik.http.routers.guestbook-post.entrypoints=websecure" + - "traefik.http.routers.guestbook-post.tls.certresolver=myresolver" + # Proxy + - "traefik.http.routers.proxy.rule=Host(`proxy.dreamsofcode.io`)" + - "traefik.http.routers.proxy.entrypoints=websecure" + - "traefik.http.routers.proxy.tls.certresolver=myresolver" + # Enable watchtower + - "com.centurylinklabs.watchtower.enable=true" + secrets: + - db-password + environment: + - POSTGRES_HOST=db + - POSTGRES_PASSWORD_FILE=/run/secrets/db-password + - POSTGRES_USER=postgres + - POSTGRES_DB=guestbook + - POSTGRES_PORT=5432 + - POSTGRES_SSLMODE=disable + deploy: + mode: replicated + replicas: 3 + restart: always + depends_on: + - db + db: + image: postgres:16 + restart: always + user: postgres + volumes: + - db-data:/var/lib/postgresql/data + secrets: + - db-password + environment: + - POSTGRES_DB=guestbook + - POSTGRES_PASSWORD_FILE=/run/secrets/db-password + expose: + - 5432 + healthcheck: + test: [ "CMD", "pg_isready" ] + interval: 10s + timeout: 5s + retries: 5 +volumes: + db-data: + letsencrypt: +secrets: + db-password: + external: true