summaryrefslogtreecommitdiff
path: root/CLAUDE.md
blob: 8b9fde0b806ff853f6b3db41f1f40818fda6a874 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Bastion — Claude Code Context

## Project Overview
Bastion is a self-hosted server system on Debian that runs multiple services in Docker containers. All containers are managed via Portainer. Nginx acts as reverse proxy sitting on all service networks.

## Domain
- Primary domain: `swave.lol`
- Subdomains: `blog.swave.lol`, `jenkins.swave.lol`

## Services / Stacks

### Portainer
- Standalone `docker run`, not in a compose file
- Web UI on port 9000
- Used to manage all other containers/stacks

### Ghost (blog)
- Dir: `ghost/`
- Compose: `ghost/compose.yml`, env: `ghost/stack.env` (for Portainer) or `.env` (for local)
- Network: `ghost_network`
- Services: ghost (port 2368), ghost-db (MySQL 8), activitypub (optional, profile-gated)
- Accessible at `https://swave.lol` and `https://blog.swave.lol`

### Git Server
- Dir: `git-server/`
- Compose: `git-server/server.yaml`, needs `docker build -t git-server .` first
- Network: `git-network` (172.22.0.0/16), static IP 172.22.0.2
- Ports: 22 (SSH), 9418 (git daemon)
- Volumes: `/var/git_ssh_keys` (public keys), `/var/git/repos` (repositories)
- Host SSH runs on a non-standard port, so port 22 is free for git

### Jenkins
- Dir: `jenkins/`
- Compose: `jenkins/docker-compose.yaml`, builds from `jenkins/Dockerfile`
- Network: `jenkins_network`
- Uses Docker-out-of-Docker (DooD): mounts `/var/run/docker.sock` to spawn sibling build containers
- Dockerfile extends `jenkins/jenkins:lts` with Docker CLI and `docker-workflow` plugin
- `--prefix=/jenkins` set via JENKINS_OPTS for path-based access
- Accessible at `https://jenkins.swave.lol` and `https://swave.lol/jenkins`
- Ports: 8080 (web UI), 50000 (agent communication)
- Volume: `/var/jenkins_home`

### Nginx (reverse proxy)
- Dir: `nginx/`
- Compose: `nginx/docker-compose.yaml`
- Network: joins `git-network` (IP 172.22.0.254), `ghost_network`, `jenkins_network`
- Ports: 80 (HTTP, redirects to HTTPS), 443 (HTTPS)
- Config mounted from `/var/nginx/conf/` on host
- SSL: Let's Encrypt certs via `run_certbot.sh`, dhparam at `/var/dh_param/`
- SSL protocols: TLSv1.2 + TLSv1.3 only
- IMPORTANT: SSL server blocks must be commented out for first run (before certs exist)

## Networking
Each stack has its own Docker network. Nginx joins all of them to reverse proxy:
- `git-network` — git-server + nginx
- `ghost_network` — ghost + ghost-db + nginx
- `jenkins_network` — jenkins + nginx

## Startup Order
1. Portainer (standalone)
2. Git Server (creates git-network)
3. Ghost (creates ghost_network)
4. Jenkins (creates jenkins_network)
5. Nginx (joins all networks, must be last)

## Key Files
- `doc/setup-guide.md` — full build instructions from fresh Debian
- `doc/Jenkinsfile.example` — example DooD pipeline
- `ghost/.env.example` — template for Ghost env vars
- `.gitignore` — excludes `.env` files (secrets)

## Conventions
- Each service lives in its own directory with its own compose file
- Compose files are named `docker-compose.yaml` or `compose.yml` or `server.yaml` (inconsistent, historical)
- Environment variables with secrets go in `.env`/`stack.env` files (gitignored)
- Nginx config is a single `nginx.conf` with multiple server blocks
- All services use `restart: always`

## TODOs (from Readme.md)
- Automatic certificate renewal for Let's Encrypt
- Better organization of nginx configs (split per service?)
- Cgit web interface for git repos
- Nexus (mentioned in Readme but not yet set up)
- Firewall rules (allow only 80, 443, 22, 8080, 8000, 9000, 9418, 50000)