Feat/open tofu #8

Merged
luke-else merged 24 commits from feat/open-tofu into main 2026-07-22 00:10:01 +00:00
33 changed files with 1235 additions and 5 deletions
Showing only changes of commit 3bfa0e6f32 - Show all commits
+38 -5
View File
@@ -1,12 +1,45 @@
# Ignore all files
**
# Ignore all files related to services
**/services
# Allow docker-compose.yml
!**/docker-compose.yml
!/*
# Allow assets folder
!assets/**
# Don't allow .env files, just env-exmaple files
!.env-example
### Terraform ###
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Include override files you do wish to add to version control using negated pattern
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
# Ignore CLI configuration files
.terraformrc
terraform.rc
+33
View File
@@ -0,0 +1,33 @@
```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
```
+35
View File
@@ -0,0 +1,35 @@
# This file is maintained automatically by "tofu init".
# Manual edits may be lost in future updates.
provider "registry.opentofu.org/hetznercloud/hcloud" {
version = "1.66.0"
constraints = "~> 1.45"
hashes = [
"h1:+R3t/5wqCb2ics5bNZ4JgtfaAa08Z6uRzXzNtwovVEY=",
"h1:9c1ECk3N9xhdQKz4NVCfYEFxebJVVeQZS3E6wrR/Hx8=",
"h1:EtYB/KjPN2cIJa6hpEaVc8q/3yf6e9IT6/uAybUGqps=",
"h1:GUupu6Fg5zFY9i4/3esiy8uHZnUrt+u2B6NaE4+8YqQ=",
"h1:JHehRJySEFRGYK+D6pFS0MTTDDRlGSQdSaKdEo0AemA=",
"h1:XF+SwyO1ttQJ0WXJ5O628O7cGk9U37sGn0o3LwWUnDQ=",
"h1:czuvCXAd8CcszXh3k3E0N6tFfQkYSNbKXo99LG+yOIc=",
"h1:dPIwO6zTxYs6bHn5yf/w/1AExaHPppCLyTrWrdzH4RE=",
"h1:gqrhnYuIBzpUvgWHITNRUMLaDcKACGlrNfrbtbtO7KY=",
"h1:iVAGP8gRbZK0kJF7SiYJRt61wz0D5AF9q+WMsrAiBI0=",
"h1:kLi29SbGCU/Z/Ch0zuNdYFSKP3mHp8zfcOpZsIN/KIQ=",
"h1:mq2+1Q/5gWJYI8XOXQCeteUg0AP7VezPOGOjkkHRQso=",
"h1:rnWTWAOlJhHtD3kkU4Qfw0bg9ko/dlH822inxYLBmfQ=",
"zh:1286cee6fb63dbcb18f53077bbb5e5d132a4e4d9f006af4e8d8edfc08d6bcdc8",
"zh:204460dacc044bda019a4a18b398e094289500c36913c7c9457f432adf31b8b2",
"zh:214175d50773481cbeaf9c9004e4121a3a1c9686c79424ebdc8ff189dd057d3e",
"zh:22b17bceff61cc13ad04a399ba87521356a3a134d4687273727473ae9eccf5f1",
"zh:368867dac5525c411de7e38f2e27de0a71854d1750867322ff2b9321128c88fb",
"zh:5289b75f8370bdbc4c6051d55cf33d0b1bd25dc6d71bfbd39b360249a37f1501",
"zh:81cb676aa50c5777df8fc80d4e69c9012330ae751f5e6f12bf6074bfd2e7c496",
"zh:ab08aead10643b21aa6b51af562b50492e12b9dd0ab7dca27a05aa63209b7d66",
"zh:af25c210d0570cf61ef767b2545bf9f3fb909178135f0e5e14bec0c1c9d07a63",
"zh:bcad66f4830c97118fa793723e53f8a4d27ddd34ea969ff259408842c2238331",
"zh:ce3ed323d75ae905d975925fa98c7054a7514c81276a485fc37da8232b53e39f",
"zh:d481bc0ef0c87ab1969c17777f526b2f59f823432d676145134c41a6d29bd98e",
"zh:ea7ef88df2c3ca154d86238920636d52a3c9066c7467543d3fa45f1e52ec2f7b",
]
}
+162
View File
@@ -0,0 +1,162 @@
# Port sources: services/*/docker-compose.yml (published ports) and services/todo.md
# (the documented UFW allow-list). dev has no firewall in architecture.md, but we add
# one anyway for baseline safety - see conversation history.
resource "hcloud_firewall" "dev" {
name = "dev-firewall"
rule { # server ssh
direction = "in"
protocol = "tcp"
port = "22"
source_ips = var.allowed_ssh_source_ips
}
rule { # gitea ssh (git.luke-else.co.uk, published as 222:22)
direction = "in"
protocol = "tcp"
port = "222"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule { # TraefikRunner http/https (git.luke-else.co.uk, cicd.luke-else.co.uk)
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule {
direction = "in"
protocol = "tcp"
port = "443"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule { # traffic from prod over the private network
direction = "in"
protocol = "tcp"
port = "1-65535"
source_ips = [var.network_ip_range]
}
rule {
direction = "in"
protocol = "udp"
port = "1-65535"
source_ips = [var.network_ip_range]
}
}
resource "hcloud_firewall" "prod" {
name = "prod-firewall"
rule { # server ssh
direction = "in"
protocol = "tcp"
port = "22"
source_ips = var.allowed_ssh_source_ips
}
rule { # Traefik http/https (Websites, Bitwarden, Misc, Tracking)
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule {
direction = "in"
protocol = "tcp"
port = "443"
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"
port = "21115"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule {
direction = "in"
protocol = "tcp"
port = "21116"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule {
direction = "in"
protocol = "udp"
port = "21116"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule { # rustdesk hbbr
direction = "in"
protocol = "tcp"
port = "21117"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule {
direction = "in"
protocol = "tcp"
port = "21119"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule { # traffic from dev over the private network
direction = "in"
protocol = "tcp"
port = "1-65535"
source_ips = [var.network_ip_range]
}
rule {
direction = "in"
protocol = "udp"
port = "1-65535"
source_ips = [var.network_ip_range]
}
}
resource "hcloud_firewall" "vpn" {
name = "vpn-firewall"
rule { # server ssh
direction = "in"
protocol = "tcp"
port = "22"
source_ips = var.allowed_ssh_source_ips
}
rule { # TraefikVPN http/https (traefik.vpn.luke-else.co.uk)
direction = "in"
protocol = "tcp"
port = "80"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule {
direction = "in"
protocol = "tcp"
port = "443"
source_ips = ["0.0.0.0/0", "::/0"]
}
rule { # OpenVPN tunnel - always direct to this server's public IP, never via a load balancer
direction = "in"
protocol = "udp"
port = "1194"
source_ips = ["0.0.0.0/0", "::/0"]
}
}
+13
View File
@@ -0,0 +1,13 @@
# Private network shared by dev and prod (see architecture.md "network" group).
# vpn is intentionally not attached to this network - it sits outside it in the diagram.
resource "hcloud_network" "main" {
name = "server-network"
ip_range = var.network_ip_range
}
resource "hcloud_network_subnet" "main" {
network_id = hcloud_network.main.id
type = "cloud"
network_zone = var.network_zone
ip_range = var.subnet_ip_range
}
+19
View File
@@ -0,0 +1,19 @@
output "dev_ipv4" {
value = hcloud_server.dev.ipv4_address
}
output "dev_private_ipv4" {
value = var.dev_private_ip
}
output "prod_ipv4" {
value = hcloud_server.prod.ipv4_address
}
output "prod_private_ipv4" {
value = var.prod_private_ip
}
output "vpn_ipv4" {
value = hcloud_server.vpn.ipv4_address
}
+43
View File
@@ -0,0 +1,43 @@
# dev: Gitea + Runner + TraefikRunner (git.luke-else.co.uk, cicd.luke-else.co.uk)
resource "hcloud_server" "dev" {
name = "dev"
server_type = var.dev_server_type
image = var.server_image
location = var.location
ssh_keys = [data.hcloud_ssh_key.main.id]
firewall_ids = [hcloud_firewall.dev.id]
network {
network_id = hcloud_network.main.id
ip = var.dev_private_ip
}
depends_on = [hcloud_network_subnet.main]
}
# prod: Traefik, Websites, Database, Bitwarden, Misc, Tracking, Rustdesk
resource "hcloud_server" "prod" {
name = "prod"
server_type = var.prod_server_type
image = var.server_image
location = var.location
ssh_keys = [data.hcloud_ssh_key.main.id]
firewall_ids = [hcloud_firewall.prod.id]
network {
network_id = hcloud_network.main.id
ip = var.prod_private_ip
}
depends_on = [hcloud_network_subnet.main]
}
# vpn: OpenVPN + TraefikVPN. Not attached to the private network (see architecture.md).
resource "hcloud_server" "vpn" {
name = "vpn"
server_type = var.vpn_server_type
image = var.server_image
location = var.location
ssh_keys = [data.hcloud_ssh_key.main.id]
firewall_ids = [hcloud_firewall.vpn.id]
}
+3
View File
@@ -0,0 +1,3 @@
data "hcloud_ssh_key" "main" {
name = var.ssh_key_name
}
+18
View File
@@ -0,0 +1,18 @@
# Copy to terraform.tfvars and fill in - terraform.tfvars itself is gitignored,
# never commit real values there.
#
# The Hetzner API token is NOT set here: export it as HCLOUD_TOKEN in your shell
# before running tofu plan/apply.
# Name of an SSH key already uploaded to your Hetzner Cloud project
# (Console > Security > SSH Keys). Required.
ssh_key_name = "your-key-name"
# Optional overrides - defaults live in variables.tf
# location = "nbg1"
# dev_server_type = "cx22"
# prod_server_type = "cx32"
# vpn_server_type = "cx22"
# dev_volume_size = 50
# prod_volume_size = 50
# allowed_ssh_source_ips = ["203.0.113.4/32"]
+82
View File
@@ -0,0 +1,82 @@
variable "location" {
description = "Hetzner Cloud datacenter location for all servers and volumes."
type = string
default = "nbg1"
}
variable "network_zone" {
description = "Hetzner Cloud network zone matching var.location."
type = string
default = "eu-central"
}
variable "server_image" {
description = "OS image used for all servers."
type = string
default = "ubuntu-24.04"
}
variable "dev_server_type" {
description = "Server type for dev (Gitea + Runner)."
type = string
default = "cx22"
}
variable "prod_server_type" {
description = "Server type for prod (Traefik, Websites, Database, Bitwarden, Misc, Tracking, Rustdesk)."
type = string
default = "cx32"
}
variable "vpn_server_type" {
description = "Server type for vpn (OpenVPN + TraefikVPN)."
type = string
default = "cx22"
}
variable "dev_volume_size" {
description = "Size in GB of the volume attached to dev (disk2 in architecture.md)."
type = number
default = 50
}
variable "prod_volume_size" {
description = "Size in GB of the volume attached to prod (disk1 in architecture.md)."
type = number
default = 50
}
variable "network_ip_range" {
description = "IP range of the private network shared by dev and prod."
type = string
default = "10.0.0.0/16"
}
variable "subnet_ip_range" {
description = "IP range of the network subnet shared by dev and prod."
type = string
default = "10.0.1.0/24"
}
variable "dev_private_ip" {
description = "Private network IP for dev."
type = string
default = "10.0.1.10"
}
variable "prod_private_ip" {
description = "Private network IP for prod."
type = string
default = "10.0.1.11"
}
variable "ssh_key_name" {
description = "Name of an SSH key already uploaded to your Hetzner Cloud project (Console > Security > SSH Keys)."
type = string
}
variable "allowed_ssh_source_ips" {
description = "CIDRs allowed to reach port 22 on every server. Narrow this to your own IP(s) once known."
type = list(string)
default = ["0.0.0.0/0", "::/0"]
}
+13
View File
@@ -0,0 +1,13 @@
terraform {
required_version = ">= 1.6.0"
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.45"
}
}
}
# Reads the token from the HCLOUD_TOKEN environment variable.
provider "hcloud" {}
+17
View File
@@ -0,0 +1,17 @@
# disk1 in architecture.md - attached to prod
resource "hcloud_volume" "prod_storage" {
name = "prod-storage"
size = var.prod_volume_size
server_id = hcloud_server.prod.id
automount = true
format = "ext4"
}
# disk2 in architecture.md - attached to dev
resource "hcloud_volume" "dev_storage" {
name = "dev-storage"
size = var.dev_volume_size
server_id = hcloud_server.dev.id
automount = true
format = "ext4"
}
+27
View File
@@ -0,0 +1,27 @@
services:
#Bitwarden ()
bitwarden:
image: "vaultwarden/server:latest"
container_name: vaultwarden
volumes:
- ./bitwarden/:/data/
networks:
- proxy
labels:
## Expose Bitwarden Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.bitwarden-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.bitwarden-insecure.rule=Host(`bitwarden.luke-else.co.uk`)"
- "traefik.http.routers.bitwarden-insecure.entrypoints=web"
- "traefik.http.routers.bitwarden.rule=Host(`bitwarden.luke-else.co.uk`)"
- "traefik.http.routers.bitwarden.entrypoints=websecure"
- "traefik.http.routers.bitwarden.tls.certresolver=myresolver"
restart: unless-stopped
networks:
proxy:
external: true
+24
View File
@@ -0,0 +1,24 @@
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
@@ -0,0 +1,54 @@
services:
#gitea (222)
gitea:
image: gitea/gitea:latest
container_name: gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- proxy
ports:
- "222:22"
environment:
- APP_NAME="gitea"
- USER_UID=1000
- USER_GID=1000
- USER=git
- RUN_MODE=prod
- DOMAIN=git.luke-else.co.uk
- SSH_DOMAIN=git.luke-else.co.uk
- HTTP_PORT=3000
- ROOT_URL=https://git.luke-else.co.uk
- SSH_PORT=222
- SSH_LISTEN_PORT=22
- DB_TYPE=sqlite3
- GITEA_service_DISABLE_REGISTRATION=true
- GITEA_server_LANDING_PAGE=/luke-else
labels:
## Expose Gitea Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.cors-gitea.headers.accesscontrolallowmethods=*"
- "traefik.http.middlewares.cors-gitea.headers.accesscontrolalloworiginlist=*"
- "traefik.http.middlewares.cors-gitea.headers.addvaryheader=true"
- "traefik.http.middlewares.cors-gitea.headers.accesscontrolallowcredentials=true"
- "traefik.http.middlewares.cors-gitea.headers.accesscontrolallowheaders=Content-Type,Authorization"
- "traefik.http.middlewares.cors-gitea.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.gitea-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.gitea-insecure.rule=Host(`git.luke-else.co.uk`)"
- "traefik.http.routers.gitea-insecure.entrypoints=web"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
- "traefik.http.routers.gitea.rule=Host(`git.luke-else.co.uk`)"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.routers.gitea.tls.certresolver=myresolver"
- "traefik.http.routers.gitea.middlewares=cors-gitea"
restart: unless-stopped
networks:
proxy:
external: true
@@ -0,0 +1,33 @@
services:
# Runner
runner:
image: gitea/act_runner:latest
container_name: gitea_runner
volumes:
- ./config.yaml:/config.yaml
- ./gitea_runner:/data
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: "https://git.luke-else.co.uk"
GITEA_RUNNER_REGISTRATION_TOKEN: "INSERT REGISTRATION TOKEN"
GITEA_RUNNER_NAME: "CICD"
labels:
## Expose cicd Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.cicd-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.cicd-insecure.rule=Host(`cicd.luke-else.co.uk`)"
- "traefik.http.routers.cicd-insecure.entrypoints=web"
- "traefik.http.routers.cicd.rule=Host(`cicd.luke-else.co.uk`)"
- "traefik.http.routers.cicd.entrypoints=websecure"
- "traefik.http.routers.cicd.tls.certresolver=myresolver"
restart: unless-stopped
networks:
proxy:
external: true
+51
View File
@@ -0,0 +1,51 @@
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
+53
View File
@@ -0,0 +1,53 @@
services:
hbbs:
image: rustdesk/rustdesk-server:latest
container_name: rustdesk-hbbs
command: hbbs
restart: unless-stopped
volumes:
- ./data:/root
networks:
- proxy
ports:
- "21115:21115/tcp"
- "21116:21116/tcp"
- "21116:21116/udp"
# - "21118:21118/tcp"
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.rustdesk-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.rustdesk-insecure.rule=Host(`rd.luke-else.co.uk`)"
- "traefik.http.routers.rustdesk-insecure.entrypoints=web"
- "traefik.http.routers.rustdesk.rule=Host(`rd.luke-else.co.uk`)"
- "traefik.http.routers.rustdesk.entrypoints=websecure"
- "traefik.http.routers.rustdesk.tls.certresolver=myresolver"
# Service
- "traefik.http.services.rustdesk.loadbalancer.server.port=21118"
hbbr:
image: rustdesk/rustdesk-server:latest
container_name: rustdesk-hbbr
command: hbbr
restart: unless-stopped
volumes:
- ./data:/root
networks:
- proxy
ports:
- "21117:21117/tcp"
- "21119:21119/tcp"
networks:
proxy:
external: true
+52
View File
@@ -0,0 +1,52 @@
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:
+46
View File
@@ -0,0 +1,46 @@
services:
traefik:
image: "traefik:latest"
container_name: "traefik"
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--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"
- "--entrypoints.websecure.transport.respondingTimeouts.writeTimeout=120s"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=contact@luke-else.co.uk"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "27017:27017"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.traefik-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.traefik-insecure.rule=Host(`traefik.luke-else.co.uk`)"
- "traefik.http.routers.traefik-insecure.entrypoints=web"
- "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.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
+40
View File
@@ -0,0 +1,40 @@
services:
traefik:
image: "traefik:latest"
container_name: "traefik"
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=contact@luke-else.co.uk"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.traefik-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.traefik-insecure.rule=Host(`traefik.cicd.luke-else.co.uk`)"
- "traefik.http.routers.traefik-insecure.entrypoints=web"
- "traefik.http.routers.traefik.rule=Host(`traefik.cicd.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.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
+40
View File
@@ -0,0 +1,40 @@
services:
traefik:
image: "traefik:latest"
container_name: "traefik"
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=contact@luke-else.co.uk"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.traefik-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.traefik-insecure.rule=Host(`traefik.vpn.luke-else.co.uk`)"
- "traefik.http.routers.traefik-insecure.entrypoints=web"
- "traefik.http.routers.traefik.rule=Host(`traefik.vpn.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.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
+24
View File
@@ -0,0 +1,24 @@
services:
dockovpn:
image: alekslitvinenk/openvpn
cap_add:
- NET_ADMIN
ports:
- 1194:1194/udp # Expose tcp if you defined HOST_TUN_PROTOCOL=tcp
environment:
HOST_ADDR: vpn.luke-else.co.uk # Your VPN server address
volumes:
- ./openvpn_conf:/opt/Dockovpn_data
labels:
## Expose vpn Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.vpn-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.vpn-insecure.rule=Host(`vpn.luke-else.co.uk`)"
- "traefik.http.routers.vpn-insecure.entrypoints=web"
- "traefik.http.routers.vpn.rule=Host(`vpn.luke-else.co.uk`)"
- "traefik.http.routers.vpn.entrypoints=websecure"
- "traefik.http.routers.vpn.tls.certresolver=myresolver"
restart: always
+8
View File
@@ -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
+103
View File
@@ -0,0 +1,103 @@
services:
#Websites luke-else.co.uk (8000) snexo.co.uk (8001) divine-couture.co.uk (80) wmgzon.luke-else.co.uk (8080)
luke-else:
image: git.luke-else.co.uk/luke-else/luke-else.co.uk
container_name: luke-else
networks:
- proxy
labels:
## Expose luke-else Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.personal-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.personal-insecure.rule=Host(`luke-else.co.uk`)"
- "traefik.http.routers.personal-insecure.entrypoints=web"
- "traefik.http.routers.personal.rule=Host(`luke-else.co.uk`)"
- "traefik.http.routers.personal.entrypoints=websecure"
- "traefik.http.routers.personal.tls.certresolver=myresolver"
restart: unless-stopped
luke-else-dev:
image: git.luke-else.co.uk/luke-else/luke-else.co.uk:dev
container_name: luke-else-dev
networks:
- proxy
labels:
## Expose luke-else Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.personal-dev-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.personal-dev-insecure.rule=Host(`dev.luke-else.co.uk`)"
- "traefik.http.routers.personal-dev-insecure.entrypoints=web"
- "traefik.http.routers.personal-dev.rule=Host(`dev.luke-else.co.uk`)"
- "traefik.http.routers.personal-dev.entrypoints=websecure"
- "traefik.http.routers.personal-dev.tls.certresolver=myresolver"
restart: unless-stopped
metarius:
image: git.luke-else.co.uk/luke-else/metarius:latest
container_name: metarius
networks:
- proxy
labels:
## Expose metarius Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.metarius-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.metarius-insecure.rule=Host(`metarius.luke-else.co.uk`)"
- "traefik.http.routers.metarius-insecure.entrypoints=web"
- "traefik.http.routers.metarius.rule=Host(`metarius.luke-else.co.uk`)"
- "traefik.http.routers.metarius.entrypoints=websecure"
- "traefik.http.routers.metarius.tls.certresolver=myresolver"
restart: unless-stopped
divine-couture:
image: git.luke-else.co.uk/luke-else/divine-couture.co.uk:latest
container_name: divine-couture
networks:
- proxy
labels:
## Expose divine-couture Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.divine-couture-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.divine-couture-insecure.rule=Host(`www.divine-couture.co.uk`)"
- "traefik.http.routers.divine-couture-insecure.entrypoints=web"
- "traefik.http.routers.divine-couture.rule=Host(`www.divine-couture.co.uk`)"
- "traefik.http.routers.divine-couture.entrypoints=websecure"
- "traefik.http.routers.divine-couture.tls.certresolver=myresolver"
restart: unless-stopped
snexo:
image: "php:apache"
container_name: snexo
volumes:
- ./snexo.co.uk/:/var/www/html
networks:
- proxy
labels:
## Expose Snexo Through Trefik ##
- "traefik.enable=true" # <== Enable traefik to proxy this container
- "traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.snexo-insecure.middlewares=redirect-web-secure"
- "traefik.http.routers.snexo-insecure.rule=Host(`snexo.co.uk`)"
- "traefik.http.routers.snexo-insecure.entrypoints=web"
- "traefik.http.routers.snexo.rule=Host(`snexo.co.uk`)"
- "traefik.http.routers.snexo.entrypoints=websecure"
- "traefik.http.routers.snexo.tls.certresolver=myresolver"
restart: unless-stopped
networks:
proxy:
external: true
+16
View File
@@ -0,0 +1,16 @@
#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
+13
View File
@@ -0,0 +1,13 @@
#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 ..
+42
View File
@@ -0,0 +1,42 @@
#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
+39
View File
@@ -0,0 +1,39 @@
#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 ..
+64
View File
@@ -0,0 +1,64 @@
# ToDo Items
## 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"
- "21116:21116/udp"
- "21117:21117/tcp"
- "21119:21119/tcp"
- Install SSH keys
- Setup unattended upgrades
- Install docker, docker-compose and apache utils.
## Traefik + TraefikRunner + Traefik VPN
- Setup htaccess -> `echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g`
- Ensure email address is correct
## Gitea
- Ensure that ports are assigned correctly for the system
# Gitea Runner
- 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
- Ensure that ports are assigned correctly for the system
## Bitwarden
- 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.
+17
View File
@@ -0,0 +1,17 @@
#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
+13
View File
@@ -0,0 +1,13 @@
#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 ..