From d0d1385bf42e46a533b0d88514617d0711240e75 Mon Sep 17 00:00:00 2001 From: Luke Else Date: Fri, 10 Jul 2026 20:13:33 +0100 Subject: [PATCH] feat: Re-structured services and updated readme --- docs/architecture.md | 33 --- infra/firewalls.tf | 7 - readme.md | 206 ++++++++++++++++-- services/Database/docker-compose.yml | 24 -- services/Misc/docker-compose.yml | 51 ----- services/Tracking/docker-compose.yml | 52 ----- services/cicd-spindown.sh | 16 -- services/cicd-spinup.sh | 13 -- .../{Development => dev}/Runners/config.yaml | 0 .../Runners/docker-compose.yml | 4 +- .../gitea-docker-compose.yml} | 0 services/dev/spindown.sh | 14 ++ services/dev/spinup.sh | 12 + .../traefik-docker-compose.yml} | 0 .../watchtower-docker-compose.yml} | 0 services/main-spindown.sh | 42 ---- services/main-spinup.sh | 39 ---- .../bitwarden-docker-compose.yml} | 0 .../rd-docker-compose.yml} | 0 services/prod/spindown.sh | 14 ++ services/prod/spinup.sh | 14 ++ services/prod/status-docker-compose.yml | 25 +++ .../traefik-docker-compose.yml} | 5 +- services/prod/watchtower-docker-compose.yml | 8 + .../web-docker-compose.yml} | 0 services/todo.md | 28 --- services/vpn-spindown.sh | 17 -- services/vpn-spinup.sh | 13 -- services/vpn/spindown.sh | 11 + services/vpn/spinup.sh | 8 + .../traefik-docker-compose.yml} | 0 .../vpn-docker-compose.yml} | 0 services/vpn/watchtower-docker-compose.yml | 8 + 33 files changed, 300 insertions(+), 364 deletions(-) delete mode 100644 docs/architecture.md delete mode 100644 services/Database/docker-compose.yml delete mode 100644 services/Misc/docker-compose.yml delete mode 100644 services/Tracking/docker-compose.yml delete mode 100755 services/cicd-spindown.sh delete mode 100755 services/cicd-spinup.sh rename services/{Development => dev}/Runners/config.yaml (100%) rename services/{Development => dev}/Runners/docker-compose.yml (95%) rename services/{Development/Gitea/docker-compose.yml => dev/gitea-docker-compose.yml} (100%) create mode 100755 services/dev/spindown.sh create mode 100755 services/dev/spinup.sh rename services/{TraefikRunner/docker-compose.yml => dev/traefik-docker-compose.yml} (100%) rename services/{Watchtower/docker-compose.yml => dev/watchtower-docker-compose.yml} (100%) delete mode 100755 services/main-spindown.sh delete mode 100755 services/main-spinup.sh rename services/{Bitwarden/docker-compose.yml => prod/bitwarden-docker-compose.yml} (100%) rename services/{Rustdesk/docker-compose.yml => prod/rd-docker-compose.yml} (100%) create mode 100755 services/prod/spindown.sh create mode 100755 services/prod/spinup.sh create mode 100644 services/prod/status-docker-compose.yml rename services/{Traefik/docker-compose.yml => prod/traefik-docker-compose.yml} (96%) create mode 100644 services/prod/watchtower-docker-compose.yml rename services/{Websites/docker-compose.yml => prod/web-docker-compose.yml} (100%) delete mode 100755 services/vpn-spindown.sh delete mode 100755 services/vpn-spinup.sh create mode 100755 services/vpn/spindown.sh create mode 100755 services/vpn/spinup.sh rename services/{TraefikVPN/docker-compose.yml => vpn/traefik-docker-compose.yml} (100%) rename services/{VPN/docker-compose.yml => vpn/vpn-docker-compose.yml} (100%) create mode 100644 services/vpn/watchtower-docker-compose.yml diff --git a/docs/architecture.md b/docs/architecture.md deleted file mode 100644 index 1395fb4..0000000 --- a/docs/architecture.md +++ /dev/null @@ -1,33 +0,0 @@ -```mermaid -architecture-beta - group cloud(cloud)[Hetzner] - - group network(cloud)[network] in cloud - - service disk1(mdi:disk)[Storage] in cloud - service disk2(mdi:disk)[Storage] in cloud - - service dev(mdi:server)[dev] in network - - service prod(mdi:server)[prod] in network - service prodfirewall(mdi:firewall)[firewall] in cloud - - service vpn(mdi:server)[vpn] in cloud - service vpnfirewall(mdi:firewall)[firewall] in cloud - - - - service gateway(mdi:web)[gateway] in cloud - - dev:L -- R:prod - disk1:B -- T:prod - disk2:B -- T:dev - - - prod:B -- T:prodfirewall - vpn:B -- T:vpnfirewall - - prodfirewall: L -- R: gateway - vpnfirewall: B -- T: gateway - -``` \ No newline at end of file diff --git a/infra/firewalls.tf b/infra/firewalls.tf index 807f33e..55528ad 100644 --- a/infra/firewalls.tf +++ b/infra/firewalls.tf @@ -72,13 +72,6 @@ resource "hcloud_firewall" "prod" { source_ips = ["0.0.0.0/0", "::/0"] } - rule { # mongo via Traefik tcp entrypoint (Database) - direction = "in" - protocol = "tcp" - port = "27017" - source_ips = ["0.0.0.0/0", "::/0"] - } - rule { # rustdesk hbbs direction = "in" protocol = "tcp" diff --git a/readme.md b/readme.md index 00ffcbc..0a21744 100644 --- a/readme.md +++ b/readme.md @@ -1,48 +1,206 @@ -# Server Repository +# Server -This repository contains various scripts and configurations for managing Docker containers and services. +Infrastructure-as-code and service definitions for luke-else.co.uk's self-hosted server estate: three [Hetzner Cloud](https://www.hetzner.com/cloud/) VPS instances provisioned with [OpenTofu](https://opentofu.org/), each running a set of Docker Compose stacks behind [Traefik](https://traefik.io/traefik/).

-## Scripts +## Contents -- `cicd-spindown.sh`: Spins down all CICD relevant Docker containers. -- `cicd-spinup.sh`: Spins up all CICD relevant Docker containers. -- `main-spindown.sh`: Spins down all Docker containers. -- `main-spinup.sh`: Spins up all Docker containers. +- [Architecture](#architecture) +- [Repository layout](#repository-layout) +- [Prerequisites](#prerequisites) +- [Provisioning the infrastructure](#provisioning-the-infrastructure-infra) +- [Deploying the services](#deploying-the-services-services) +- [Service inventory](#service-inventory) +- [First-time setup](#first-time-setup) +- [Development container](#development-container) +- [Security notes](#security-notes) -## Services +## Architecture -### Bitwarden +Three servers, one shared private network: -Configuration for Bitwarden is located in [Bitwarden/docker-compose.yml](Bitwarden/docker-compose.yml). +```mermaid +architecture-beta + group cloud(cloud)[Hetzner] -### Database + group network(cloud)[network] in cloud -Configuration for MongoDB is located in [Database/docker-compose.yml](Database/docker-compose.yml). + service disk1(mdi:disk)[Storage] in cloud + service disk2(mdi:disk)[Storage] in cloud -### Misc + service dev(mdi:server)[dev] in network -Configuration for miscellaneous services is located in [Misc/docker-compose.yml](Misc/docker-compose.yml). + service prod(mdi:server)[prod] in network + service prodfirewall(mdi:firewall)[firewall] in cloud -### Tracking + service vpn(mdi:server)[vpn] in cloud + service vpnfirewall(mdi:firewall)[firewall] in cloud -Configuration for tracking services is located in [Tracking/docker-compose.yml](Tracking/docker-compose.yml). + service gateway(mdi:web)[gateway] in cloud -### Traefik + dev:L -- R:prod + disk1:B -- T:prod + disk2:B -- T:dev -Configuration for Traefik is located in [Traefik/docker-compose.yml](Traefik/docker-compose.yml). + prod:B -- T:prodfirewall + vpn:B -- T:vpnfirewall -### TraefikRunner + prodfirewall: L -- R: gateway + vpnfirewall: B -- T: gateway +``` -Configuration for TraefikRunner is located in [TraefikRunner/docker-compose.yml](TraefikRunner/docker-compose.yml). +`gateway` represents the public internet, not a provisioned resource. -### Websites +| Server | Purpose | Network | Volume | +|---|---|---|---| +| `dev` | Gitea, CI runner, dev-facing Traefik | Private network only (no public firewall exposure beyond CI/CD) | `dev-storage` | +| `prod` | Public-facing websites, Bitwarden, RustDesk, status page, prod Traefik | Private network + public firewall | `prod-storage` | +| `vpn` | OpenVPN + its own Traefik | **Not** attached to the private network — kept isolated so a compromised VPN endpoint can't pivot to `dev`/`prod` | none | -Configuration for websites is located in [Websites/docker-compose.yml](Websites/docker-compose.yml). +`dev` and `prod` share a private Hetzner network (`10.0.1.0/24` by default) so CI/CD on `dev` can reach deployment targets on `prod` without exposing that traffic publicly. `vpn` is deliberately kept off this network. Each server has its own Hetzner Cloud Firewall (see `infra/firewalls.tf`) that only opens the ports actually used by the compose stacks running on it, plus SSH restricted to `var.allowed_ssh_source_ips`. -## ToDo +## Repository layout -See [todo.md](todo.md) for a list of tasks and configurations that need to be completed. \ No newline at end of file +``` +. +├── infra/ # OpenTofu (Terraform-compatible) config — provisions the 3 servers, network, firewalls, volumes +│ ├── servers.tf +│ ├── network.tf +│ ├── firewalls.tf +│ ├── volumes.tf +│ ├── ssh.tf +│ ├── variables.tf +│ ├── outputs.tf +│ ├── versions.tf +│ └── terraform.tfvars.example +├── services/ # Docker Compose stacks, grouped by which server they run on +│ ├── dev/ # Gitea + CI runner + Traefik (git.luke-else.co.uk, cicd.luke-else.co.uk) +│ ├── prod/ # Websites, Bitwarden, RustDesk, status page + Traefik +│ ├── vpn/ # OpenVPN + Traefik +│ └── todo.md # Outstanding manual setup/hardening tasks +├── docs/ +│ └── architecture.md # Source of the architecture diagram above +├── .devcontainer/ # Git submodule: shared devcontainer for working on this repo (OpenTofu tooling) +└── assets/ +``` + +Each of `services/dev`, `services/prod`, `services/vpn` follows the same convention: one `*-docker-compose.yml` (or subdirectory, e.g. `Runners/`) per logical service, plus a `spinup.sh` / `spindown.sh` pair that brings up or tears down every stack on that host in the right order. + +## Prerequisites + +- A [Hetzner Cloud](https://console.hetzner.cloud/) project and API token +- An SSH key uploaded to that project (Console → Security → SSH Keys) +- [OpenTofu](https://opentofu.org/docs/intro/install/) `>= 1.6.0` +- Docker + the Compose plugin on each target server +- DNS records for the domains in [Service inventory](#service-inventory) pointed at the relevant server's public IP + +## Provisioning the infrastructure (`infra/`) + +```sh +cd infra +export HCLOUD_TOKEN=your-hetzner-api-token # never commit this +cp terraform.tfvars.example terraform.tfvars +$EDITOR terraform.tfvars # set ssh_key_name at minimum + +tofu init +tofu plan +tofu apply +``` + +This creates: +- `hcloud_server.dev`, `hcloud_server.prod`, `hcloud_server.vpn` +- `hcloud_network.main` + subnet, shared by `dev` and `prod` +- `hcloud_firewall.dev` / `.prod` / `.vpn`, scoped to the ports each host actually uses +- `hcloud_volume.dev_storage` / `.prod_storage` + +Useful outputs: `tofu output dev_ipv4`, `tofu output prod_ipv4`, `tofu output vpn_ipv4`. + +`terraform.tfvars` and any `*.tfvars` file are gitignored — never commit real values there. Defaults for server sizes, locations, and IP ranges live in `infra/variables.tf` and can be overridden per-environment via `terraform.tfvars`. + +## Deploying the services (`services/`) + +Once a server exists, copy the relevant `services//` directory to it (e.g. `scp -r services/prod user@:~/services`) and run the matching script from inside that directory: + +```sh +# on dev +./spinup.sh # Traefik → Gitea Runner → Watchtower +./spindown.sh # reverse order, then prunes images/volumes + +# on prod +./spinup.sh # Traefik, then (after a 20s cert/registry settle) Watchtower, status, websites, Bitwarden, RustDesk +./spindown.sh + +# on vpn +./spinup.sh # Traefik → OpenVPN → Watchtower +./spindown.sh +``` + +Each stack can also be managed individually with plain Compose, e.g.: + +```sh +cd services/prod +docker compose -f bitwarden-docker-compose.yml up -d +docker compose -f bitwarden-docker-compose.yml down +``` + +All three hosts run [Watchtower](https://containrrr.dev/watchtower/) polling every 60s with cleanup enabled, so images are kept current automatically once deployed — the spinup scripts only need to be re-run after adding/removing a service or changing compose files. + +Every public-facing service is fronted by its host's own Traefik instance, terminating TLS via Let's Encrypt (`tlschallenge`, port 80/443). Each stack joins an external `proxy` Docker network and opts in via `traefik.enable=true` labels rather than publishing ports directly (RustDesk and the Gitea SSH port are the deliberate exceptions, since they aren't HTTP). + +## Service inventory + +### `dev` + +| Service | Compose file | Domain(s) | +|---|---|---| +| Traefik | `traefik-docker-compose.yml` | `traefik.cicd.luke-else.co.uk` | +| Gitea | `gitea-docker-compose.yml` | `git.luke-else.co.uk` (HTTP), SSH on `222` | +| Gitea Actions runner | `Runners/docker-compose.yml` | `cicd.luke-else.co.uk` | +| Watchtower | `watchtower-docker-compose.yml` | — | + +### `prod` + +| Service | Compose file | Domain(s) | +|---|---|---| +| Traefik | `traefik-docker-compose.yml` | `traefik.luke-else.co.uk` | +| Websites | `web-docker-compose.yml` | `luke-else.co.uk`, `dev.luke-else.co.uk`, `metarius.luke-else.co.uk`, `www.divine-couture.co.uk`, `snexo.co.uk` | +| Status page (Uptime Kuma) | `status-docker-compose.yml` | `status.luke-else.co.uk` | +| Bitwarden (Vaultwarden) | `bitwarden-docker-compose.yml` | `bitwarden.luke-else.co.uk` | +| RustDesk relay (hbbs/hbbr) | `rd-docker-compose.yml` | `rd.luke-else.co.uk`, ports `21115-21119` | +| Watchtower | `watchtower-docker-compose.yml` | — | + +### `vpn` + +| Service | Compose file | Domain(s) | +|---|---|---| +| Traefik | `traefik-docker-compose.yml` | `traefik.vpn.luke-else.co.uk` | +| OpenVPN (Dockovpn) | `vpn-docker-compose.yml` | `vpn.luke-else.co.uk`, UDP `1194` | +| Watchtower | `watchtower-docker-compose.yml` | — | + +## First-time setup + +A few things need manual attention before a stack is fully live — tracked in [`services/todo.md`](services/todo.md), summarized here: + +- **Gitea Actions runner**: set a real `GITEA_RUNNER_REGISTRATION_TOKEN` in `services/dev/Runners/docker-compose.yml` (generate one from the Gitea admin UI) before starting the runner. +- **Traefik dashboard auth**: the committed basic-auth hash is a placeholder. Generate your own with `echo $(htpasswd -nb user password) | sed -e 's/\$/\$\$/g'` and replace the `traefik-auth` middleware value in each `traefik-docker-compose.yml`. +- **General host hardening**: non-root user, UFW, unattended-upgrades, Docker install — see `services/todo.md`. + +## Development container + +`.devcontainer` is a git submodule providing a ready-to-use OpenTofu development environment (VS Code + OpenTofu/Docker/Mermaid extensions). After cloning: + +```sh +git submodule update --init --recursive +``` + +Then reopen the repo in VS Code with the Dev Containers extension. + +## Security notes + +- Real secrets (`HCLOUD_TOKEN`, `*.tfvars`, `.env` files) must never be committed — see `.gitignore`. +- SSH is restricted to `var.allowed_ssh_source_ips` on every host; narrow this from the default `0.0.0.0/0` once you know your own egress IP(s). +- `vpn` is intentionally excluded from the private network so that a compromised VPN endpoint cannot reach `dev` or `prod` directly. +- Firewalls are allowlists scoped per host in `infra/firewalls.tf` — only ports actually used by that host's compose stacks (plus the cross-host private network range) are open. diff --git a/services/Database/docker-compose.yml b/services/Database/docker-compose.yml deleted file mode 100644 index 3d1a9a3..0000000 --- a/services/Database/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -services: - -#MongoDB (27017) - mongodb: - image: "mongo:latest" - container_name: mongoDB - volumes: - - ./mongo/:/data/db - networks: - - proxy - labels: - - "traefik.enable=true" - - "traefik.tcp.routers.mongodb.rule=HostSNI(`*`)" - - "traefik.tcp.routers.mongodb.entrypoints=mongo" - - "traefik.tcp.routers.mongodb.service=mongodb" - - "traefik.tcp.services.mongodb.loadbalancer.server.port=27017" - environment: - MONGO_INITDB_ROOT_USERNAME: root - MONGO_INITDB_ROOT_PASSWORD: rootpassword - restart: unless-stopped - -networks: - proxy: - external: true \ No newline at end of file diff --git a/services/Misc/docker-compose.yml b/services/Misc/docker-compose.yml deleted file mode 100644 index 7914b79..0000000 --- a/services/Misc/docker-compose.yml +++ /dev/null @@ -1,51 +0,0 @@ -services: - status: - image: louislam/uptime-kuma:latest - container_name: status - volumes: - - ./uptime-kuma/data:/app/data - networks: - - proxy - labels: - ## Expose uptime-kuma Through Trefik ## - - "traefik.enable=true" # <== Enable traefik to proxy this container - - - "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.status-insecure.middlewares=redirect-web-secure" - - "traefik.http.routers.status-insecure.rule=Host(`status.luke-else.co.uk`)" - - "traefik.http.routers.status-insecure.entrypoints=web" - - - "traefik.http.routers.status.rule=Host(`status.luke-else.co.uk`)" - - "traefik.http.routers.status.entrypoints=websecure" - - "traefik.http.routers.status.tls.certresolver=myresolver" - restart: unless-stopped - - portainer: - image: portainer/portainer-ce:latest - container_name: portainer - security_opt: - - no-new-privileges:true - volumes: - - /etc/localtime:/etc/localtime:ro - - /var/run/docker.sock:/var/run/docker.sock:ro - - ./portainer-data:/data - networks: - - proxy - labels: - ## Expose portainer Through Trefik ## - - "traefik.enable=true" # <== Enable traefik to proxy this container - - - "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.portainer-insecure.middlewares=redirect-web-secure" - - "traefik.http.routers.portainer-insecure.rule=Host(`portainer.luke-else.co.uk`)" - - "traefik.http.routers.portainer-insecure.entrypoints=web" - - - "traefik.http.routers.portainer.rule=Host(`portainer.luke-else.co.uk`)" - - "traefik.http.services.portainer.loadbalancer.server.port=9000" - - "traefik.http.routers.portainer.entrypoints=websecure" - - "traefik.http.routers.portainer.tls.certresolver=myresolver" - restart: unless-stopped - -networks: - proxy: - external: true \ No newline at end of file diff --git a/services/Tracking/docker-compose.yml b/services/Tracking/docker-compose.yml deleted file mode 100644 index 6fe612a..0000000 --- a/services/Tracking/docker-compose.yml +++ /dev/null @@ -1,52 +0,0 @@ -services: - ackee: - image: electerious/ackee - container_name: ackee - environment: - - WAIT_HOSTS=mongo:27017 - - ACKEE_MONGODB=mongodb://mongo-ackee:27017/ackee - env_file: - - .env - expose: - - 3000 - networks: - - tracking - - proxy - labels: - ## Expose Ackee Through Trefik ## - - "traefik.enable=true" # <== Enable traefik to proxy this container - - # Enable CORS headers - - "traefik.http.middlewares.cors-tracking.headers.accesscontrolallowmethods=*" - - "traefik.http.middlewares.cors-tracking.headers.accesscontrolalloworiginlist=https://luke-else.co.uk" - - "traefik.http.middlewares.cors-tracking.headers.accesscontrolallowcredentials=true" - - "traefik.http.middlewares.cors-tracking.headers.accesscontrolallowheaders=Content-Type,Authorization" - - "traefik.http.middlewares.cors-tracking.headers.addvaryheader=true" - - "traefik.http.middlewares.cors-tracking.headers.accesscontrolmaxage=100" - - - "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.ackee-insecure.middlewares=redirect-web-secure" - - "traefik.http.routers.ackee-insecure.rule=Host(`tracking.luke-else.co.uk`)" - - "traefik.http.routers.ackee-insecure.entrypoints=web" - - - "traefik.http.routers.ackee.rule=Host(`tracking.luke-else.co.uk`)" - - "traefik.http.routers.ackee.entrypoints=websecure" - - "traefik.http.routers.ackee.tls.certresolver=myresolver" - - "traefik.http.routers.ackee.middlewares=cors-tracking" - depends_on: - - mongo - restart: unless-stopped - - mongo: - image: mongo - container_name: mongo-ackee - volumes: - - ./data:/data/db - networks: - - tracking - restart: unless-stopped - -networks: - proxy: - external: true - tracking: \ No newline at end of file diff --git a/services/cicd-spindown.sh b/services/cicd-spindown.sh deleted file mode 100755 index 1e3d49c..0000000 --- a/services/cicd-spindown.sh +++ /dev/null @@ -1,16 +0,0 @@ -#Script file for spinning down all CICD relevant docker-containers - cd ./Development/Runners/ - docker compose down - cd ../.. - -cd ./TraefikRunner/ -docker compose down -cd .. - -cd ./Watchtower/ -docker compose down -cd .. - -docker rmi $(docker images -q) -docker system prune -f -a -docker volume prune -f -a \ No newline at end of file diff --git a/services/cicd-spinup.sh b/services/cicd-spinup.sh deleted file mode 100755 index 6a3b139..0000000 --- a/services/cicd-spinup.sh +++ /dev/null @@ -1,13 +0,0 @@ -#Script file for spinning up all docker-containers - -cd ./TraefikRunner/ -docker compose pull && docker compose up -d -cd .. - - cd ./Development/Runners/ - docker compose pull && docker compose up -d - cd ../.. - -cd ./Watchtower/ -docker compose pull && docker compose up -d -cd .. \ No newline at end of file diff --git a/services/Development/Runners/config.yaml b/services/dev/Runners/config.yaml similarity index 100% rename from services/Development/Runners/config.yaml rename to services/dev/Runners/config.yaml diff --git a/services/Development/Runners/docker-compose.yml b/services/dev/Runners/docker-compose.yml similarity index 95% rename from services/Development/Runners/docker-compose.yml rename to services/dev/Runners/docker-compose.yml index f9f5acd..0e1bb51 100644 --- a/services/Development/Runners/docker-compose.yml +++ b/services/dev/Runners/docker-compose.yml @@ -13,7 +13,7 @@ services: CONFIG_FILE: /config.yaml GITEA_INSTANCE_URL: "https://git.luke-else.co.uk" GITEA_RUNNER_REGISTRATION_TOKEN: "INSERT REGISTRATION TOKEN" - GITEA_RUNNER_NAME: "CICD" + GITEA_RUNNER_NAME: "CICD#1" labels: ## Expose cicd Through Trefik ## - "traefik.enable=true" # <== Enable traefik to proxy this container @@ -30,4 +30,4 @@ services: networks: proxy: - external: true \ No newline at end of file + external: true diff --git a/services/Development/Gitea/docker-compose.yml b/services/dev/gitea-docker-compose.yml similarity index 100% rename from services/Development/Gitea/docker-compose.yml rename to services/dev/gitea-docker-compose.yml diff --git a/services/dev/spindown.sh b/services/dev/spindown.sh new file mode 100755 index 0000000..5e71bd2 --- /dev/null +++ b/services/dev/spindown.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Script file for spinning down all dev docker-containers +cd "$(dirname "$0")" + +cd Runners +docker compose down +cd .. + +docker compose -f traefik-docker-compose.yml down +docker compose -f watchtower-docker-compose.yml down + +docker rmi $(docker images -q) +docker system prune -f -a +docker volume prune -f -a diff --git a/services/dev/spinup.sh b/services/dev/spinup.sh new file mode 100755 index 0000000..6d9bfcc --- /dev/null +++ b/services/dev/spinup.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Script file for spinning up all dev docker-containers +set -e +cd "$(dirname "$0")" + +docker compose -f traefik-docker-compose.yml pull && docker compose -f traefik-docker-compose.yml up -d + +cd Runners +docker compose pull && docker compose up -d +cd .. + +docker compose -f watchtower-docker-compose.yml pull && docker compose -f watchtower-docker-compose.yml up -d diff --git a/services/TraefikRunner/docker-compose.yml b/services/dev/traefik-docker-compose.yml similarity index 100% rename from services/TraefikRunner/docker-compose.yml rename to services/dev/traefik-docker-compose.yml diff --git a/services/Watchtower/docker-compose.yml b/services/dev/watchtower-docker-compose.yml similarity index 100% rename from services/Watchtower/docker-compose.yml rename to services/dev/watchtower-docker-compose.yml diff --git a/services/main-spindown.sh b/services/main-spindown.sh deleted file mode 100755 index 1012835..0000000 --- a/services/main-spindown.sh +++ /dev/null @@ -1,42 +0,0 @@ -#Script file for spinning down all docker-containers - -cd ./Websites/ -docker compose down -cd .. - -cd ./Tracking/ -docker compose down -cd .. - - - cd ./Development/Gitea/ - docker compose down - cd ../.. - -cd ./Database/ -docker compose down -cd .. - -cd ./Bitwarden/ -docker compose down -cd .. - -cd ./Rustdesk/ -docker compose down -cd .. - -cd ./Misc/ -docker compose down -cd .. - -cd ./Watchtower/ -docker compose down -cd .. - -cd ./Traefik/ -docker compose down -cd .. - -docker rmi $(docker images -q) -docker system prune -f -a -docker volume prune -f -a \ No newline at end of file diff --git a/services/main-spinup.sh b/services/main-spinup.sh deleted file mode 100755 index d8f8a03..0000000 --- a/services/main-spinup.sh +++ /dev/null @@ -1,39 +0,0 @@ -#Script file for spinning up all docker-containers - -cd ./Traefik/ -docker compose pull && docker compose up -d -cd .. - - cd ./Development/Gitea/ - docker compose pull && docker compose up -d - cd ../.. - -sleep 20 # Allow Gitea + registry to start up before starting the rest of the services - -cd ./Watchtower/ -docker compose pull && docker compose up -d -cd .. - -cd ./Tracking/ -docker compose pull && docker compose up -d -cd .. - -cd ./Websites/ -docker compose pull && docker compose up -d -cd .. - -cd ./Database/ -docker compose pull && docker compose up -d -cd .. - -cd ./Bitwarden/ -docker compose pull && docker compose up -d -cd .. - -cd ./Rustdesk/ -docker compose pull && docker compose up -d -cd .. - -cd ./Misc/ -docker compose pull && docker compose up -d -cd .. \ No newline at end of file diff --git a/services/Bitwarden/docker-compose.yml b/services/prod/bitwarden-docker-compose.yml similarity index 100% rename from services/Bitwarden/docker-compose.yml rename to services/prod/bitwarden-docker-compose.yml diff --git a/services/Rustdesk/docker-compose.yml b/services/prod/rd-docker-compose.yml similarity index 100% rename from services/Rustdesk/docker-compose.yml rename to services/prod/rd-docker-compose.yml diff --git a/services/prod/spindown.sh b/services/prod/spindown.sh new file mode 100755 index 0000000..665ab2b --- /dev/null +++ b/services/prod/spindown.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Script file for spinning down all prod docker-containers +cd "$(dirname "$0")" + +docker compose -f web-docker-compose.yml down +docker compose -f status-docker-compose.yml down +docker compose -f bitwarden-docker-compose.yml down +docker compose -f rd-docker-compose.yml down +docker compose -f watchtower-docker-compose.yml down +docker compose -f traefik-docker-compose.yml down + +docker rmi $(docker images -q) +docker system prune -f -a +docker volume prune -f -a diff --git a/services/prod/spinup.sh b/services/prod/spinup.sh new file mode 100755 index 0000000..8fa967e --- /dev/null +++ b/services/prod/spinup.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Script file for spinning up all prod docker-containers +set -e +cd "$(dirname "$0")" + +docker compose -f traefik-docker-compose.yml pull && docker compose -f traefik-docker-compose.yml up -d + +sleep 20 # Allow Traefik + registry auth to settle before starting the rest of the services + +docker compose -f watchtower-docker-compose.yml pull && docker compose -f watchtower-docker-compose.yml up -d +docker compose -f status-docker-compose.yml pull && docker compose -f status-docker-compose.yml up -d +docker compose -f web-docker-compose.yml pull && docker compose -f web-docker-compose.yml up -d +docker compose -f bitwarden-docker-compose.yml pull && docker compose -f bitwarden-docker-compose.yml up -d +docker compose -f rd-docker-compose.yml pull && docker compose -f rd-docker-compose.yml up -d diff --git a/services/prod/status-docker-compose.yml b/services/prod/status-docker-compose.yml new file mode 100644 index 0000000..0e833c2 --- /dev/null +++ b/services/prod/status-docker-compose.yml @@ -0,0 +1,25 @@ +services: + status: + image: louislam/uptime-kuma:latest + container_name: status + volumes: + - ./uptime-kuma/data:/app/data + networks: + - proxy + labels: + ## Expose uptime-kuma Through Trefik ## + - "traefik.enable=true" # <== Enable traefik to proxy this container + + - "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https" + - "traefik.http.routers.status-insecure.middlewares=redirect-web-secure" + - "traefik.http.routers.status-insecure.rule=Host(`status.luke-else.co.uk`)" + - "traefik.http.routers.status-insecure.entrypoints=web" + + - "traefik.http.routers.status.rule=Host(`status.luke-else.co.uk`)" + - "traefik.http.routers.status.entrypoints=websecure" + - "traefik.http.routers.status.tls.certresolver=myresolver" + restart: unless-stopped + +networks: + proxy: + external: true diff --git a/services/Traefik/docker-compose.yml b/services/prod/traefik-docker-compose.yml similarity index 96% rename from services/Traefik/docker-compose.yml rename to services/prod/traefik-docker-compose.yml index c2b613a..53e89ac 100644 --- a/services/Traefik/docker-compose.yml +++ b/services/prod/traefik-docker-compose.yml @@ -8,7 +8,6 @@ services: - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - - "--entrypoints.mongo.address=:27017" - "--entrypoints.web.transport.respondingTimeouts.readTimeout=120s" - "--entrypoints.websecure.transport.respondingTimeouts.readTimeout=120s" - "--entrypoints.web.transport.respondingTimeouts.writeTimeout=120s" @@ -36,11 +35,11 @@ services: - "traefik.http.routers.traefik.rule=Host(`traefik.luke-else.co.uk`)" - "traefik.http.routers.traefik.entrypoints=websecure" - "traefik.http.routers.traefik.service=api@internal" - - "traefik.http.routers.traefik.tls.certresolver=myresolver" + - "traefik.http.routers.traefik.tls.certresolver=myresolver" - "traefik.http.routers.traefik.middlewares=traefik-auth" - "traefik.http.middlewares.traefik-auth.basicauth.users=user:$$2y$$05$$s/vPphFtSO2fWJR7SYkEb.90UwPDRM3aOKqgOF/rme/3fUQ5tvpTS" restart: unless-stopped networks: proxy: - name: proxy \ No newline at end of file + name: proxy diff --git a/services/prod/watchtower-docker-compose.yml b/services/prod/watchtower-docker-compose.yml new file mode 100644 index 0000000..ee735d3 --- /dev/null +++ b/services/prod/watchtower-docker-compose.yml @@ -0,0 +1,8 @@ +services: + watchtower: + image: nickfedor/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_POLL_INTERVAL=60 diff --git a/services/Websites/docker-compose.yml b/services/prod/web-docker-compose.yml similarity index 100% rename from services/Websites/docker-compose.yml rename to services/prod/web-docker-compose.yml diff --git a/services/todo.md b/services/todo.md index a53d118..eccd34c 100644 --- a/services/todo.md +++ b/services/todo.md @@ -3,13 +3,6 @@ ## General - Setup non root user -- UFW should be setup to keep VPS secure and only allow for: - - - https - - http - - ssh - - ftp - - 27017 - "21115:21115/tcp" - "21116:21116/tcp" @@ -17,8 +10,6 @@ - "21117:21117/tcp" - "21119:21119/tcp" -- Install SSH keys -- Setup unattended upgrades - Install docker, docker-compose and apache utils. ## Traefik + TraefikRunner + Traefik VPN @@ -34,15 +25,6 @@ - Ensure that a registration token has been setup before continuing -## Tracking - -Create a .env file with the following content: - -```sh -ACKEE_USERNAME=luke-else -ACKEE_PASSWORD=XXX -``` - ## Websites - Ensure website files are copied over @@ -52,13 +34,3 @@ ACKEE_PASSWORD=XXX - Ensure that all data is fully encrypted during transfer. - Ensure that ports are assigned correctly for the system - -## Rustdesk - -- No additional setup required bar the ports - -## Database - -- Ensure that mysql root password, user and default database are updated. -- Ensure that mongo root password, and user are updated. -- Ensure database ports are correctly assigned and do not have to pass through traefik. diff --git a/services/vpn-spindown.sh b/services/vpn-spindown.sh deleted file mode 100755 index 7cd9ef1..0000000 --- a/services/vpn-spindown.sh +++ /dev/null @@ -1,17 +0,0 @@ -#Script file for spinning down all CICD relevant docker-containers - -cd ./VPN/ -docker compose down -cd .. - -cd ./TraefikVPN/ -docker compose down -cd .. - -cd ./Watchtower/ -docker compose down -cd .. - -docker rmi $(docker images -q) -docker system prune -f -a -docker volume prune -f -a \ No newline at end of file diff --git a/services/vpn-spinup.sh b/services/vpn-spinup.sh deleted file mode 100755 index 4cc5159..0000000 --- a/services/vpn-spinup.sh +++ /dev/null @@ -1,13 +0,0 @@ -#Script file for spinning up all docker-containers - -cd ./TraefikRunner/ -docker compose pull && docker compose up -d -cd .. - -cd ./VPN/ -docker compose pull && docker compose up -d -cd .. - -cd ./Watchtower/ -docker compose pull && docker compose up -d -cd .. \ No newline at end of file diff --git a/services/vpn/spindown.sh b/services/vpn/spindown.sh new file mode 100755 index 0000000..c30233f --- /dev/null +++ b/services/vpn/spindown.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Script file for spinning down all vpn docker-containers +cd "$(dirname "$0")" + +docker compose -f vpn-docker-compose.yml down +docker compose -f traefik-docker-compose.yml down +docker compose -f watchtower-docker-compose.yml down + +docker rmi $(docker images -q) +docker system prune -f -a +docker volume prune -f -a diff --git a/services/vpn/spinup.sh b/services/vpn/spinup.sh new file mode 100755 index 0000000..14250a8 --- /dev/null +++ b/services/vpn/spinup.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Script file for spinning up all vpn docker-containers +set -e +cd "$(dirname "$0")" + +docker compose -f traefik-docker-compose.yml pull && docker compose -f traefik-docker-compose.yml up -d +docker compose -f vpn-docker-compose.yml pull && docker compose -f vpn-docker-compose.yml up -d +docker compose -f watchtower-docker-compose.yml pull && docker compose -f watchtower-docker-compose.yml up -d diff --git a/services/TraefikVPN/docker-compose.yml b/services/vpn/traefik-docker-compose.yml similarity index 100% rename from services/TraefikVPN/docker-compose.yml rename to services/vpn/traefik-docker-compose.yml diff --git a/services/VPN/docker-compose.yml b/services/vpn/vpn-docker-compose.yml similarity index 100% rename from services/VPN/docker-compose.yml rename to services/vpn/vpn-docker-compose.yml diff --git a/services/vpn/watchtower-docker-compose.yml b/services/vpn/watchtower-docker-compose.yml new file mode 100644 index 0000000..ee735d3 --- /dev/null +++ b/services/vpn/watchtower-docker-compose.yml @@ -0,0 +1,8 @@ +services: + watchtower: + image: nickfedor/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_POLL_INTERVAL=60