summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArseney300 <Arseney300@gmail.com>2026-02-20 02:02:10 +0700
committerArseney300 <Arseney300@gmail.com>2026-02-20 02:02:10 +0700
commit688e8bcd85709811a9140237c2e394c5df6d5652 (patch)
treefa2d0e8084dfc9af8059432f727c266959437e11
parentebddef6a320b219889152b594cfc7adef5f6764b (diff)
Add full server setup guide
Step-by-step instructions to build the bastion server from a fresh Debian install: Docker, Portainer, Git Server, Ghost, Jenkins, Nginx with SSL. Includes network architecture, startup order, and ports summary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
-rw-r--r--doc/setup-guide.md340
1 files changed, 340 insertions, 0 deletions
diff --git a/doc/setup-guide.md b/doc/setup-guide.md
new file mode 100644
index 0000000..581dee1
--- /dev/null
+++ b/doc/setup-guide.md
@@ -0,0 +1,340 @@
+# Bastion Server — Setup Guide
+
+Full instruction to build the server from a fresh Debian installation.
+
+## Prerequisites
+
+- Fresh Debian server
+- Root access
+- Domain `swave.lol` with DNS A records pointing to the server:
+ - `swave.lol`
+ - `blog.swave.lol`
+ - `jenkins.swave.lol`
+
+
+## 1. Install Docker
+
+Based on https://docs.docker.com/engine/install/debian/#install-using-the-repository
+
+```bash
+# Install prerequisites
+apt-get update
+apt-get install -y ca-certificates curl gnupg
+
+# Add Docker GPG key
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
+chmod a+r /etc/apt/keyrings/docker.asc
+
+# Add Docker repository
+echo \
+ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
+ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
+ tee /etc/apt/sources.list.d/docker.list > /dev/null
+
+# Install Docker
+apt-get update
+apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+
+# Verify
+docker run hello-world
+```
+
+
+## 2. Clone the bastion repository
+
+```bash
+cd /root/Projects
+git clone <your-repo-url> bastion
+cd bastion
+```
+
+
+## 3. Start Portainer
+
+Portainer manages all other containers and stacks via web UI.
+
+```bash
+docker run -d \
+ --name="portainer" \
+ --restart on-failure \
+ -p 9000:9000 \
+ -p 8000:8000 \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v portainer_data:/data \
+ portainer/portainer-ce:latest
+```
+
+Access Portainer at `http://<server-ip>:9000` and create admin account.
+
+
+## 4. Git Server
+
+### 4.1 Create host directories
+
+```bash
+# Directory for SSH public keys (for git access)
+mkdir -p /var/git_ssh_keys
+
+# Directory for git repositories
+mkdir -p /var/git/repos
+
+# Copy your public SSH keys for git access
+# cp ~/.ssh/id_rsa.pub /var/git_ssh_keys/mykey.pub
+```
+
+### 4.2 Build and start
+
+```bash
+cd /root/Projects/bastion/git-server
+
+# Build the git-server image
+docker build -t git-server .
+
+# Start (this also creates the git-network)
+docker compose -f server.yaml up -d
+```
+
+### 4.3 Create a test repository
+
+```bash
+# On the server
+cd /var/git/repos
+git init --bare test.git
+chown -R 1000:1000 test.git # git user inside container
+
+# From a client machine
+git clone ssh://git@<server-ip>/repos/test.git
+```
+
+
+## 5. Ghost (Blog)
+
+### 5.1 Prepare environment
+
+```bash
+cd /root/Projects/bastion/ghost
+
+# Copy the mysql init script to the expected location
+mkdir -p /var/lib/docker/mysql-init-script
+cp mysql-init-script/create-multiple-databases.sh /var/lib/docker/mysql-init-script/
+
+# Edit stack.env (or .env for non-Portainer use) with your credentials
+# IMPORTANT: Change default passwords before first run!
+```
+
+Key settings in `stack.env`:
+- `DOMAIN` — your domain (e.g. `swave.lol`)
+- `DATABASE_ROOT_PASSWORD` — MySQL root password
+- `DATABASE_USER` / `DATABASE_PASSWORD` — Ghost database credentials
+- `UPLOAD_LOCATION` — where Ghost stores content
+
+### 5.2 Start Ghost
+
+```bash
+cd /root/Projects/bastion/ghost
+docker compose up -d
+```
+
+Ghost will be available at `http://<server-ip>:2368` for testing before Nginx is configured.
+
+To start with ActivityPub support (optional):
+```bash
+docker compose --profile activitypub up -d
+```
+
+
+## 6. Jenkins
+
+### 6.1 Create host directories
+
+```bash
+mkdir -p /var/jenkins_home
+```
+
+### 6.2 Build and start
+
+```bash
+cd /root/Projects/bastion/jenkins
+
+# Build Jenkins image (includes Docker CLI and docker-workflow plugin)
+docker compose build
+
+# Start Jenkins
+docker compose up -d
+```
+
+### 6.3 Get initial admin password
+
+```bash
+docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
+```
+
+Jenkins will be available at `http://<server-ip>:8080/jenkins` for initial setup.
+
+### 6.4 Jenkins build setup (DooD)
+
+Jenkins uses Docker-out-of-Docker: it spawns sibling containers on the host for builds.
+Each project defines its own build image in the Jenkinsfile:
+
+```groovy
+pipeline {
+ agent {
+ docker { image 'node:20' }
+ }
+ stages {
+ stage('Build') {
+ steps {
+ sh 'npm install && npm run build'
+ }
+ }
+ }
+}
+```
+
+See `doc/Jenkinsfile.example` for a full multi-stage example.
+
+
+## 7. Nginx (Reverse Proxy + SSL)
+
+Nginx must be started AFTER Git Server, Ghost, and Jenkins, because it joins
+their networks as external.
+
+### 7.1 Create host directories
+
+```bash
+# Nginx config directory
+mkdir -p /var/nginx/conf
+
+# Copy nginx.conf
+cp /root/Projects/bastion/nginx/nginx.conf /var/nginx/conf/
+
+# DH parameters (this takes a few minutes)
+mkdir -p /var/dh_param
+openssl dhparam -out /var/dh_param/dhparam-2048.pem 2048
+
+# Let's Encrypt directories
+mkdir -p /var/letsencrypt/etc
+mkdir -p /var/letsencrypt/lts_site
+
+# Copy the ACME challenge placeholder page
+cp /root/Projects/bastion/nginx/letsencrypt/index.html /var/letsencrypt/lts_site/
+```
+
+### 7.2 First run — HTTP only (no SSL yet)
+
+Before we have SSL certificates, we need to temporarily disable the SSL server
+blocks so Nginx can start and serve the ACME challenge for certbot.
+
+```bash
+# Edit the nginx.conf copy on the host to comment out SSL server blocks
+# Keep only the port 80 server block
+nano /var/nginx/conf/nginx.conf
+```
+
+Comment out everything from `# Ghost — swave.lol` to the end of file.
+Keep only the `listen 80` server block.
+
+```bash
+cd /root/Projects/bastion/nginx
+docker compose up -d
+```
+
+### 7.3 Obtain SSL certificates
+
+```bash
+cd /root/Projects/bastion/nginx
+bash run_certbot.sh
+```
+
+This requests certificates for:
+- `swave.lol`
+- `blog.swave.lol`
+- `jenkins.swave.lol`
+
+IMPORTANT: All DNS records must be pointing to the server before running certbot.
+
+### 7.4 Enable SSL
+
+```bash
+# Restore full nginx.conf with SSL blocks
+cp /root/Projects/bastion/nginx/nginx.conf /var/nginx/conf/
+
+# Restart Nginx
+cd /root/Projects/bastion/nginx
+docker compose restart
+```
+
+### 7.5 Verify
+
+All services should now be accessible:
+
+| URL | Service |
+|-----|---------|
+| `https://swave.lol` | Ghost (blog) |
+| `https://blog.swave.lol` | Ghost (blog, alias) |
+| `https://swave.lol/jenkins` | Jenkins (path-based) |
+| `https://jenkins.swave.lol` | Jenkins (subdomain) |
+| `http://<server-ip>:9000` | Portainer |
+| `ssh://git@<server-ip>/repos/<repo>.git` | Git (SSH) |
+| `git://<server-ip>/<repo>.git` | Git (daemon, read-only) |
+
+
+## Network Architecture
+
+```
+git-network (172.22.0.0/16)
+├── git-server (172.22.0.2)
+└── nginx (172.22.0.254)
+
+ghost_network
+├── ghost
+├── ghost-db
+├── activitypub (optional)
+└── nginx
+
+jenkins_network
+├── jenkins
+└── nginx
+```
+
+Nginx sits on all networks so it can reverse proxy to every service.
+
+
+## Startup Order
+
+The correct order to start all services:
+
+```bash
+# 1. Portainer (standalone, no dependencies)
+docker run -d --name="portainer" --restart on-failure \
+ -p 9000:9000 -p 8000:8000 \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v portainer_data:/data portainer/portainer-ce:latest
+
+# 2. Git Server (creates git-network)
+docker compose -f /root/Projects/bastion/git-server/server.yaml up -d
+
+# 3. Ghost (creates ghost_network)
+docker compose -f /root/Projects/bastion/ghost/compose.yml up -d
+
+# 4. Jenkins (creates jenkins_network)
+docker compose -f /root/Projects/bastion/jenkins/docker-compose.yaml up -d
+
+# 5. Nginx (joins all networks — must be last)
+docker compose -f /root/Projects/bastion/nginx/docker-compose.yaml up -d
+```
+
+
+## Ports Summary
+
+| Port | Service | Protocol |
+|------|---------|----------|
+| 22 | Git Server (SSH) | TCP |
+| 80 | Nginx (HTTP, redirects to 443) | TCP |
+| 443 | Nginx (HTTPS) | TCP |
+| 2368 | Ghost (direct, for testing) | TCP |
+| 8080 | Jenkins (direct, for testing) | TCP |
+| 9000 | Portainer (web UI) | TCP |
+| 9418 | Git Server (git daemon) | TCP |
+| 50000 | Jenkins (agent communication) | TCP |