Feat/open tofu #8
@@ -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
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -72,13 +72,6 @@ resource "hcloud_firewall" "prod" {
|
|||||||
source_ips = ["0.0.0.0/0", "::/0"]
|
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
|
rule { # rustdesk hbbs
|
||||||
direction = "in"
|
direction = "in"
|
||||||
protocol = "tcp"
|
protocol = "tcp"
|
||||||
|
|||||||
@@ -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/).
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="assets/images/main.png" width="70%">
|
<img src="assets/images/main.png" width="70%">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Scripts
|
## Contents
|
||||||
|
|
||||||
- `cicd-spindown.sh`: Spins down all CICD relevant Docker containers.
|
- [Architecture](#architecture)
|
||||||
- `cicd-spinup.sh`: Spins up all CICD relevant Docker containers.
|
- [Repository layout](#repository-layout)
|
||||||
- `main-spindown.sh`: Spins down all Docker containers.
|
- [Prerequisites](#prerequisites)
|
||||||
- `main-spinup.sh`: Spins up all Docker containers.
|
- [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.
|
```
|
||||||
|
.
|
||||||
|
├── 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/<host>/` directory to it (e.g. `scp -r services/prod user@<prod_ipv4>:~/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.
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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:
|
|
||||||
@@ -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
|
|
||||||
@@ -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 ..
|
|
||||||
+2
-2
@@ -13,7 +13,7 @@ services:
|
|||||||
CONFIG_FILE: /config.yaml
|
CONFIG_FILE: /config.yaml
|
||||||
GITEA_INSTANCE_URL: "https://git.luke-else.co.uk"
|
GITEA_INSTANCE_URL: "https://git.luke-else.co.uk"
|
||||||
GITEA_RUNNER_REGISTRATION_TOKEN: "INSERT REGISTRATION TOKEN"
|
GITEA_RUNNER_REGISTRATION_TOKEN: "INSERT REGISTRATION TOKEN"
|
||||||
GITEA_RUNNER_NAME: "CICD"
|
GITEA_RUNNER_NAME: "CICD#1"
|
||||||
labels:
|
labels:
|
||||||
## Expose cicd Through Trefik ##
|
## Expose cicd Through Trefik ##
|
||||||
- "traefik.enable=true" # <== Enable traefik to proxy this container
|
- "traefik.enable=true" # <== Enable traefik to proxy this container
|
||||||
@@ -30,4 +30,4 @@ services:
|
|||||||
|
|
||||||
networks:
|
networks:
|
||||||
proxy:
|
proxy:
|
||||||
external: true
|
external: true
|
||||||
Executable
+14
@@ -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
|
||||||
Executable
+12
@@ -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
|
||||||
@@ -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
|
|
||||||
@@ -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 ..
|
|
||||||
Executable
+14
@@ -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
|
||||||
Executable
+14
@@ -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
|
||||||
@@ -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
|
||||||
@@ -8,7 +8,6 @@ services:
|
|||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
- "--entrypoints.websecure.address=:443"
|
- "--entrypoints.websecure.address=:443"
|
||||||
- "--entrypoints.mongo.address=:27017"
|
|
||||||
- "--entrypoints.web.transport.respondingTimeouts.readTimeout=120s"
|
- "--entrypoints.web.transport.respondingTimeouts.readTimeout=120s"
|
||||||
- "--entrypoints.websecure.transport.respondingTimeouts.readTimeout=120s"
|
- "--entrypoints.websecure.transport.respondingTimeouts.readTimeout=120s"
|
||||||
- "--entrypoints.web.transport.respondingTimeouts.writeTimeout=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.rule=Host(`traefik.luke-else.co.uk`)"
|
||||||
- "traefik.http.routers.traefik.entrypoints=websecure"
|
- "traefik.http.routers.traefik.entrypoints=websecure"
|
||||||
- "traefik.http.routers.traefik.service=api@internal"
|
- "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.routers.traefik.middlewares=traefik-auth"
|
||||||
- "traefik.http.middlewares.traefik-auth.basicauth.users=user:$$2y$$05$$s/vPphFtSO2fWJR7SYkEb.90UwPDRM3aOKqgOF/rme/3fUQ5tvpTS"
|
- "traefik.http.middlewares.traefik-auth.basicauth.users=user:$$2y$$05$$s/vPphFtSO2fWJR7SYkEb.90UwPDRM3aOKqgOF/rme/3fUQ5tvpTS"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
proxy:
|
proxy:
|
||||||
name: proxy
|
name: proxy
|
||||||
@@ -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
|
||||||
@@ -3,13 +3,6 @@
|
|||||||
## General
|
## General
|
||||||
|
|
||||||
- Setup non root user
|
- Setup non root user
|
||||||
- UFW should be setup to keep VPS secure and only allow for:
|
|
||||||
|
|
||||||
- https
|
|
||||||
- http
|
|
||||||
- ssh
|
|
||||||
- ftp
|
|
||||||
- 27017
|
|
||||||
|
|
||||||
- "21115:21115/tcp"
|
- "21115:21115/tcp"
|
||||||
- "21116:21116/tcp"
|
- "21116:21116/tcp"
|
||||||
@@ -17,8 +10,6 @@
|
|||||||
- "21117:21117/tcp"
|
- "21117:21117/tcp"
|
||||||
- "21119:21119/tcp"
|
- "21119:21119/tcp"
|
||||||
|
|
||||||
- Install SSH keys
|
|
||||||
- Setup unattended upgrades
|
|
||||||
- Install docker, docker-compose and apache utils.
|
- Install docker, docker-compose and apache utils.
|
||||||
|
|
||||||
## Traefik + TraefikRunner + Traefik VPN
|
## Traefik + TraefikRunner + Traefik VPN
|
||||||
@@ -34,15 +25,6 @@
|
|||||||
|
|
||||||
- Ensure that a registration token has been setup before continuing
|
- 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
|
## Websites
|
||||||
|
|
||||||
- Ensure website files are copied over
|
- Ensure website files are copied over
|
||||||
@@ -52,13 +34,3 @@ ACKEE_PASSWORD=XXX
|
|||||||
|
|
||||||
- Ensure that all data is fully encrypted during transfer.
|
- Ensure that all data is fully encrypted during transfer.
|
||||||
- Ensure that ports are assigned correctly for the system
|
- 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.
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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 ..
|
|
||||||
Executable
+11
@@ -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
|
||||||
Executable
+8
@@ -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
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user