241 lines
3.8 KiB
Markdown
241 lines
3.8 KiB
Markdown
# go-fishing
|
|
|
|
Fish in HTTP or SSH. Written in go :)
|
|
|
|
# Deployment
|
|
|
|
`go-fishing` runs on a single VPS with Docker Compose.
|
|
|
|
Images are stored in the private Gitea registry at:
|
|
|
|
```text
|
|
git.hat.fish
|
|
```
|
|
|
|
## Traffic
|
|
|
|
```text
|
|
fishing.jp.wtf:22
|
|
-> go-fishing SSH server
|
|
|
|
fishing.jp.wtf:80
|
|
-> Nginx
|
|
-> redirect to HTTPS
|
|
|
|
fishing.jp.wtf:443
|
|
-> Nginx
|
|
-> go-fishing HTTP server
|
|
|
|
VPS:2222
|
|
-> OpenSSH
|
|
```
|
|
|
|
Port `22` belongs to the application.
|
|
|
|
The VPS's administrative SSH server listens on `2222`.
|
|
|
|
## Docker
|
|
|
|
The Compose stack contains:
|
|
|
|
```text
|
|
go-fishing
|
|
postgres
|
|
```
|
|
|
|
The application image is:
|
|
|
|
```text
|
|
git.hat.fish/jaron/go-fishing:latest
|
|
```
|
|
|
|
PostgreSQL uses:
|
|
|
|
```text
|
|
postgres:18-alpine
|
|
```
|
|
|
|
PostgreSQL data is stored in a Docker volume.
|
|
|
|
The database is only accessible through the Docker network.
|
|
|
|
```text
|
|
go-fishing -> db:5432
|
|
```
|
|
|
|
There is no reason to expose PostgreSQL publicly.
|
|
|
|
## HTTP
|
|
|
|
The Go application exposes an HTTP server on:
|
|
|
|
```text
|
|
9900
|
|
```
|
|
|
|
It is not intended to be accessed directly.
|
|
|
|
Nginx proxies HTTPS traffic to it:
|
|
|
|
```text
|
|
https://fishing.jp.wtf
|
|
-> nginx :443
|
|
-> 127.0.0.1:9900
|
|
```
|
|
|
|
A minimal Nginx configuration looks like:
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name fishing.jp.wtf;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/fishing.jp.wtf/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/fishing.jp.wtf/privkey.pem;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:9900;
|
|
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
|
|
server {
|
|
listen 80;
|
|
server_name fishing.jp.wtf;
|
|
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
```
|
|
|
|
Nginx does not handle SSH traffic.
|
|
|
|
## TLS
|
|
|
|
TLS certificates come from Let's Encrypt and are managed by Certbot.
|
|
|
|
Certificate files live under:
|
|
|
|
```text
|
|
/etc/letsencrypt/live/fishing.jp.wtf/
|
|
```
|
|
|
|
The important files are:
|
|
|
|
```text
|
|
fullchain.pem
|
|
privkey.pem
|
|
```
|
|
|
|
The certificate was created with:
|
|
|
|
```bash
|
|
sudo certbot --nginx -d fishing.jp.wtf
|
|
```
|
|
|
|
Renewal is handled automatically by Certbot.
|
|
|
|
Check it with:
|
|
|
|
```bash
|
|
systemctl status certbot.timer
|
|
```
|
|
|
|
Test renewal with:
|
|
|
|
```bash
|
|
sudo certbot renew --dry-run
|
|
```
|
|
|
|
The Go application does not manage TLS itself.
|
|
|
|
## SSH
|
|
|
|
`go-fishing` runs an SSH server using Charm Wish.
|
|
|
|
Users connect with:
|
|
|
|
```bash
|
|
ssh user@fishing.jp.wtf
|
|
```
|
|
|
|
The VPS itself is administered with:
|
|
|
|
```bash
|
|
ssh -p 2222 user@<vps>
|
|
```
|
|
|
|
Nginx and the TLS certificate are unrelated to SSH.
|
|
|
|
## Configuration
|
|
|
|
Secrets and environment-specific configuration live in `.env` on the VPS.
|
|
|
|
Example:
|
|
|
|
```env
|
|
COOKIE_STORE_SECRET="top secret secret"
|
|
DB_CONNECTION_STRING="postgres://dev:dev@localhost:5432/go_fishing"
|
|
POSTGRES_USER="dev"
|
|
POSTGRES_PASSWORD="dev"
|
|
POSTGRES_DB="go_fishing"
|
|
ENV="DEVELOPMENT"
|
|
```
|
|
|
|
## Deployment
|
|
|
|
Deployment is currently manual.
|
|
|
|
Build and push:
|
|
|
|
```bash
|
|
# If building for same CPU architecture
|
|
docker build -t git.hat.fish/jaron/go-fishing:latest .
|
|
# If building from another architecture
|
|
docker build --platform=linux/amd64 -t git.hat.fish/jaron/go-fishing:latest .
|
|
|
|
docker push git.hat.fish/jaron/go-fishing:latest
|
|
```
|
|
|
|
Deploy on the VPS:
|
|
|
|
```bash
|
|
docker compose pull
|
|
docker compose up -d
|
|
```
|
|
|
|
That's the deployment process.
|
|
|
|
There is no CI/CD pipeline yet.
|
|
|
|
## Infrastructure
|
|
|
|
The complete production setup is:
|
|
|
|
```text
|
|
DNS
|
|
└── fishing.jp.wtf
|
|
|
|
|
v
|
|
VPS
|
|
├── OpenSSH :2222
|
|
├── Nginx :80/:443
|
|
│ ├── Let's Encrypt certificate
|
|
│ └── proxy -> localhost:9900
|
|
└── Docker Compose
|
|
├── go-fishing
|
|
│ └── SSH :22
|
|
└── PostgreSQL
|
|
└── Docker volume
|
|
|
|
Gitea
|
|
└── container registry
|
|
```
|
|
|
|
There is no Kubernetes, managed database, load balancer, deployment platform, or other infrastructure layer.
|
|
|
|
None is currently needed.
|