From 05eb81aa6461969c99107ca8f87cac1419462b30 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 12 Mar 2025 19:16:31 -0400 Subject: [PATCH] base template --- .woodpecker.yml | 149 ++++++++++++++++++++++++++++++++++ docker-compose.production.yml | 6 ++ docker-compose.staging.yml | 6 ++ stack.production.yml | 44 ++++++++++ stack.staging.yml | 37 +++++++++ 5 files changed, 242 insertions(+) create mode 100644 .woodpecker.yml create mode 100644 docker-compose.production.yml create mode 100644 docker-compose.staging.yml create mode 100644 stack.production.yml create mode 100644 stack.staging.yml diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..498f98b --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,149 @@ +# build:0 +labels: + location: manager +clone: + git: + image: woodpeckerci/plugin-git + settings: + partial: false + depth: 1 +when: + branch: [main] +steps: + # Build and Push for Staging + build-push-staging: + name: build-push-staging + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + DOCKER_REGISTRY_USER: + from_secret: DOCKER_REGISTRY_USER + DOCKER_REGISTRY_PASSWORD: + from_secret: DOCKER_REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "nameserver 1.1.1.1" > /etc/resolv.conf + - echo "nameserver 1.0.0.1" >> /etc/resolv.conf + - HOSTNAME=$(docker info --format "{{.Name}}") + - echo "Building on $HOSTNAME" + - echo "$${DOCKER_REGISTRY_PASSWORD}" | docker login -u "$${DOCKER_REGISTRY_USER}" --password-stdin + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - docker compose -f docker-compose.staging.yml build --no-cache + - docker compose -f docker-compose.staging.yml push + when: + branch: main + event: push + + # Deploy Staging + deploy-staging: + name: deploy-staging + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "nameserver 1.1.1.1" > /etc/resolv.conf + - echo "nameserver 1.0.0.1" >> /etc/resolv.conf + - HOSTNAME=$(docker info --format "{{.Name}}") + - echo "Deploying on $HOSTNAME" + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - docker stack deploy --with-registry-auth -c ./stack.staging.yml $${CI_REPO_NAME}-staging + when: + branch: main + event: push + + # Wait for Deploy to Complete + wait-for-deploy-staging: + name: wait-for-deploy-staging + image: woodpeckerci/plugin-docker-buildx + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "nameserver 1.1.1.1" > /etc/resolv.conf + - echo "nameserver 1.0.0.1" >> /etc/resolv.conf + - sleep 20 + when: + branch: main + event: push + + # Build and Push for Production + build-push-production: + name: build-push-production + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + DOCKER_REGISTRY_USER: + from_secret: DOCKER_REGISTRY_USER + DOCKER_REGISTRY_PASSWORD: + from_secret: DOCKER_REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "nameserver 1.1.1.1" > /etc/resolv.conf + - echo "nameserver 1.0.0.1" >> /etc/resolv.conf + - HOSTNAME=$(docker info --format "{{.Name}}") + - echo "Building on $HOSTNAME" + - echo "$${DOCKER_REGISTRY_PASSWORD}" | docker login -u "$${DOCKER_REGISTRY_USER}" --password-stdin + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - docker compose -f docker-compose.production.yml build --no-cache + - docker compose -f docker-compose.production.yml push + when: + branch: main + event: [push, cron] + + # Deploy Production + deploy-production: + name: deploy-production + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "nameserver 1.1.1.1" > /etc/resolv.conf + - echo "nameserver 1.0.0.1" >> /etc/resolv.conf + - HOSTNAME=$(docker info --format "{{.Name}}") + - echo "Deploying on $HOSTNAME" + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - docker stack deploy --with-registry-auth -c ./stack.production.yml $${CI_REPO_NAME} + when: + branch: main + event: [push, cron] + + # Cleanup Staging Environment + cleanup-staging: + name: cleanup-staging + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "nameserver 1.1.1.1" > /etc/resolv.conf + - echo "nameserver 1.0.0.1" >> /etc/resolv.conf + - HOSTNAME=$(docker info --format "{{.Name}}") + - echo "Cleaning up staging environment on $HOSTNAME" + - for i in {1..5}; do docker stack rm $${CI_REPO_NAME}-staging && break || sleep 10; done + - docker compose -f docker-compose.staging.yml down + - docker compose -f docker-compose.staging.yml rm -f + when: + branch: main + event: [push, cron] + status: success \ No newline at end of file diff --git a/docker-compose.production.yml b/docker-compose.production.yml new file mode 100644 index 0000000..d0e3da8 --- /dev/null +++ b/docker-compose.production.yml @@ -0,0 +1,6 @@ +services: + midtownplaydio: + build: + context: ./docker/midtownplaydio + dockerfile: Dockerfile.production + image: git.nixc.us/colin/midtownplaydio:production \ No newline at end of file diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml new file mode 100644 index 0000000..5636c9a --- /dev/null +++ b/docker-compose.staging.yml @@ -0,0 +1,6 @@ +services: + midtownplaydio: + build: + context: ./docker/midtownplaydio + dockerfile: Dockerfile + image: git.nixc.us/colin/midtownplaydio:staging \ No newline at end of file diff --git a/stack.production.yml b/stack.production.yml new file mode 100644 index 0000000..290b9ba --- /dev/null +++ b/stack.production.yml @@ -0,0 +1,44 @@ +networks: + traefik: + external: true + +services: + midtownplaydio: + image: git.nixc.us/colin/midtownplaydio:production + networks: + - traefik + deploy: + replicas: 1 + placement: + constraints: + - node.hostname == macmini1 + + # update_config: + # delay: 0s + # parallelism: 2 + # order: start-first + labels: + traefik.enable: "true" + traefik.http.routers.production_midtownplaydio.rule: "Host(`midtownplaydio.nixc.us`)" + traefik.http.routers.production_midtownplaydio.entrypoints: "websecure" + traefik.http.routers.production_midtownplaydio.tls: "true" + traefik.http.routers.production_midtownplaydio.tls.certresolver: "letsencryptresolver" + traefik.http.services.production_midtownplaydio.loadbalancer.server.port: "3000" + traefik.docker.network: "traefik" + # traefik.http.services.production_midtownplaydio.loadbalancer.healthcheck.path: "/health" + # traefik.http.services.production_midtownplaydio.loadbalancer.healthcheck.interval: "30s" + # traefik.http.services.production_midtownplaydio.loadbalancer.healthcheck.timeout: "5s" + + # Security headers middleware + traefik.http.middlewares.secure-headers.headers.stsSeconds: 63072000 + traefik.http.middlewares.secure-headers.headers.stsIncludeSubdomains: "true" + traefik.http.middlewares.secure-headers.headers.stsPreload: "true" + traefik.http.middlewares.secure-headers.headers.forceSTSHeader: "true" + traefik.http.middlewares.secure-headers.headers.frameDeny: "true" + traefik.http.middlewares.secure-headers.headers.contentTypeNosniff: "true" + traefik.http.middlewares.secure-headers.headers.browserXssFilter: "true" + traefik.http.middlewares.secure-headers.headers.referrerPolicy: "no-referrer" + traefik.http.middlewares.secure-headers.headers.featurePolicy: "camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none'" + + # Attach security headers middleware to the router + traefik.http.routers.production_midtownplaydio.middlewares: "secure-headers" diff --git a/stack.staging.yml b/stack.staging.yml new file mode 100644 index 0000000..86a0650 --- /dev/null +++ b/stack.staging.yml @@ -0,0 +1,37 @@ +version: '3.8' + +networks: + traefik: + external: true + default: + +services: + midtownplaydio: + image: git.nixc.us/colin/midtownplaydio:staging + networks: + - traefik + - default + deploy: + replicas: 1 + placement: + constraints: + - node.hostname == ingress.nixc.us + preferences: + - spread: node.id + restart_policy: + condition: on-failure + update_config: + delay: 20s + parallelism: 1 + order: start-first + labels: + traefik.enable: "true" + traefik.http.routers.staging_midtownplaydio.rule: "Host(`staging.midtownplaydio.nixc.us`)" + traefik.http.routers.staging_midtownplaydio.entrypoints: "websecure" + traefik.http.routers.staging_midtownplaydio.tls: "true" + traefik.http.routers.staging_midtownplaydio.tls.certresolver: "letsencryptresolver" + traefik.http.services.staging_midtownplaydio.loadbalancer.server.port: "3000" + traefik.docker.network: "traefik" + # traefik.http.services.staging_midtownplaydio.loadbalancer.healthcheck.path: "/health" + # traefik.http.services.staging_midtownplaydio.loadbalancer.healthcheck.interval: "30s" + # traefik.http.services.staging_midtownplaydio.loadbalancer.healthcheck.timeout: "5s"