Restructure repository to manage both server2 and caddy-vps
- Create server2/ directory and migrate Xray proxy config, Clash config, and utility scripts - Create caddy-vps/ directory and add Caddyfile reverse proxy configuration - Update .gitea/workflows/deploy.yml CI/CD pipeline to validate JSON/YAML and check Caddyfile formatting/syntax - Deploy configurations sequentially to both servers - Update README.md to document multi-server topology and CI/CD behavior Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
|
git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
|
||||||
git checkout ${{ github.sha }}
|
git checkout ${{ github.sha }}
|
||||||
- name: Validate JSON
|
- name: Validate JSON (Xray)
|
||||||
run: python3 -c "import json; json.load(open('xray-config.json'))"
|
run: python3 -c "import json; json.load(open('server2/xray-config.json'))"
|
||||||
- name: Validate YAML
|
- name: Validate YAML (Clash Meta)
|
||||||
run: pip install pyyaml -q --break-system-packages && python3 -c "import yaml; yaml.safe_load(open('clash-meta.yaml'))"
|
run: pip install pyyaml -q --break-system-packages && python3 -c "import yaml; yaml.safe_load(open('server2/clash-meta.yaml'))"
|
||||||
|
- name: Install Caddy for validation
|
||||||
|
run: |
|
||||||
|
curl -L -o caddy "https://caddyserver.com/api/download?os=linux&arch=amd64"
|
||||||
|
chmod +x caddy
|
||||||
|
- name: Validate Caddyfile formatting
|
||||||
|
run: ./caddy fmt --check caddy-vps/Caddyfile
|
||||||
|
- name: Validate Caddyfile syntax
|
||||||
|
run: ./caddy validate --config caddy-vps/Caddyfile --adapter caddyfile
|
||||||
|
|
||||||
security:
|
security:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -32,7 +40,7 @@ jobs:
|
|||||||
- name: Check for secrets
|
- name: Check for secrets
|
||||||
run: |
|
run: |
|
||||||
FOUND=0
|
FOUND=0
|
||||||
if grep -rE '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----' --include='*.json' --include='*.yaml' --include='*.yml' --include='*.md' .; then
|
if grep -rE '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----' --include='*.json' --include='*.yaml' --include='*.yml' --include='*.md' --include='Caddyfile' .; then
|
||||||
echo "ERROR: Private key found in repo"
|
echo "ERROR: Private key found in repo"
|
||||||
FOUND=1
|
FOUND=1
|
||||||
fi
|
fi
|
||||||
@@ -49,7 +57,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
|
git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
|
||||||
git checkout ${{ github.sha }}
|
git checkout ${{ github.sha }}
|
||||||
- name: Deploy xray config
|
- name: Setup SSH
|
||||||
env:
|
env:
|
||||||
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
||||||
run: |
|
run: |
|
||||||
@@ -57,5 +65,12 @@ jobs:
|
|||||||
echo "$VPS_SSH_KEY" > ~/.ssh/id_ed25519
|
echo "$VPS_SSH_KEY" > ~/.ssh/id_ed25519
|
||||||
chmod 600 ~/.ssh/id_ed25519
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
ssh-keyscan -H 158.101.140.85 >> ~/.ssh/known_hosts 2>/dev/null
|
ssh-keyscan -H 158.101.140.85 >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
scp xray-config.json jimmyg@158.101.140.85:/tmp/xray-config.json
|
ssh-keyscan -H 161.33.182.109 >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
ssh jimmyg@158.101.140.85 "sudo cp /tmp/xray-config.json /usr/local/etc/xray/config.json && sudo chmod 644 /usr/local/etc/xray/config.json && sudo systemctl restart xray"
|
- name: Deploy Xray config to server2
|
||||||
|
run: |
|
||||||
|
scp server2/xray-config.json jimmyg@158.101.140.85:/tmp/xray-config.json
|
||||||
|
ssh jimmyg@158.101.140.85 "sudo cp /tmp/xray-config.json /usr/local/etc/xray/config.json && sudo chmod 600 /usr/local/etc/xray/config.json && sudo systemctl restart xray"
|
||||||
|
- name: Deploy Caddy config to caddy-vps
|
||||||
|
run: |
|
||||||
|
scp caddy-vps/Caddyfile ubuntu@161.33.182.109:/tmp/Caddyfile
|
||||||
|
ssh ubuntu@161.33.182.109 "sudo cp /tmp/Caddyfile /etc/caddy/Caddyfile && sudo chmod 644 /etc/caddy/Caddyfile && sudo systemctl reload caddy"
|
||||||
|
|||||||
@@ -1,65 +1,62 @@
|
|||||||
# VPS Oracle Japan - Proxy Server
|
# VPS Infrastructure Management - Oracle Japan
|
||||||
> CI/CD last tested: 2026-02-18
|
|
||||||
|
|
||||||
## Server Info
|
Multi-server infrastructure configuration and deployment rules for Tokyo VPS instances.
|
||||||
- IP: 158.101.140.85
|
|
||||||
- OS: Ubuntu 24.04 LTS
|
|
||||||
- SSH: `ssh server2`
|
|
||||||
|
|
||||||
## VLESS + Reality (Xray)
|
---
|
||||||
- Protocol: VLESS
|
|
||||||
- Port: 443
|
|
||||||
- UUID: 7bb711be-47a2-4273-aa8e-45bcb6216f70
|
|
||||||
- Flow: xtls-rprx-vision
|
|
||||||
- Security: reality
|
|
||||||
- SNI: www.microsoft.com
|
|
||||||
- Public Key: 203MXpq2G45goHJB7gmdEorwORVeyBOvEISlcLCrWms
|
|
||||||
- Private Key: *(stored on server only — see `/usr/local/etc/xray/config.json`)*
|
|
||||||
- Short ID: abcd1234
|
|
||||||
- Fingerprint: safari
|
|
||||||
|
|
||||||
### Client URI
|
## 🖥️ Server Registry
|
||||||
```
|
|
||||||
vless://7bb711be-47a2-4273-aa8e-45bcb6216f70@158.101.140.85:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=www.microsoft.com&fp=safari&pbk=203MXpq2G45goHJB7gmdEorwORVeyBOvEISlcLCrWms&sid=abcd1234&type=tcp#Japan-VPS
|
### 1. `server2` (Tokyo Region)
|
||||||
|
* **Public IP**: `158.101.140.85`
|
||||||
|
* **Tailscale IP**: `100.70.115.1` (`oracle-tokyo`)
|
||||||
|
* **Role**: Fast Outbound Network Proxy & Network-level AdGuard DNS resolver.
|
||||||
|
* **SSH Access**: `ssh server2` (uses user `jimmyg`, key `~/.ssh/id_ed25519_vps`)
|
||||||
|
* **Running Services**:
|
||||||
|
* **Xray**: VLESS+Reality protocol on port `443`.
|
||||||
|
* **Tailscale**: Active exit node to route external mesh network traffic.
|
||||||
|
* **WireGuard**: Client tunnel on port `51820`.
|
||||||
|
* **AdGuard Home**: Network-wide ad blocker and local resolver on DNS port `53` and Web UI port `3000` (Tailscale bound).
|
||||||
|
* **fail2ban**: Brute-force mitigation active for SSH.
|
||||||
|
|
||||||
|
### 2. `caddy-vps` (Tokyo Region)
|
||||||
|
* **Public IP**: `161.33.182.109`
|
||||||
|
* **Tailscale IP**: `100.109.198.126` (`caddy-proxy`)
|
||||||
|
* **Role**: Public edge reverse proxy with HTTPS (Let's Encrypt TLS) and Authelia forward-auth integration.
|
||||||
|
* **SSH Access**: `ssh caddy-vps` (uses user `ubuntu`, key `~/.ssh/id_ed25519_vps`)
|
||||||
|
* **Running Services**:
|
||||||
|
* **Caddy**: Edge web server listening on ports `80` and `443` to route traffic to local Synology NAS services.
|
||||||
|
* **Tailscale**: Node agent to connect to local NAS services on the mesh network.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Repository Structure
|
||||||
|
```text
|
||||||
|
vps-oracle-jp/
|
||||||
|
├── server2/ # Configurations & tools for server2
|
||||||
|
│ ├── xray-config.json # VLESS+Reality server proxy config
|
||||||
|
│ ├── clash-meta.yaml # Clash Meta mobile configuration
|
||||||
|
│ ├── japan-vps-qr.png # Shadowrocket client setup QR
|
||||||
|
│ ├── clash-meta-qr.png # Clash Meta client setup QR
|
||||||
|
│ ├── harden.sh # Server security hardening script
|
||||||
|
│ ├── setup-tailscale-exit-node.sh # Exit node router config script
|
||||||
|
│ └── uptime-check.sh # Server service health check utility
|
||||||
|
├── caddy-vps/ # Configurations for caddy-vps
|
||||||
|
│ └── Caddyfile # Active reverse proxy routing rules
|
||||||
|
└── .gitea/
|
||||||
|
└── workflows/deploy.yml # Automated multi-server CI/CD pipeline
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tailscale
|
---
|
||||||
- VPS: 100.70.115.1 (oracle-tokyo, exit node enabled)
|
|
||||||
- NAS: 100.78.131.124 (ds224plus)
|
|
||||||
- Phone: 100.83.55.44 (huawei-mate-70)
|
|
||||||
- iPhone: 100.111.7.83 (iphone181)
|
|
||||||
- Mac: 100.65.185.12 (macbook-air)
|
|
||||||
|
|
||||||
## Files
|
## 🚀 CI/CD Automated Deployment
|
||||||
- `xray-config.json` — Xray server config (deployed to `/usr/local/etc/xray/config.json`)
|
Deployments are managed automatically on Gitea via Gitea Actions whenever changes are pushed to the `main` branch:
|
||||||
- `clash-meta.yaml` — Clash Meta client config for Android
|
|
||||||
- `japan-vps-qr.png` — Shadowrocket QR code
|
|
||||||
- `clash-meta-qr.png` — Clash Meta QR code
|
|
||||||
|
|
||||||
## AdGuard Home
|
1. **Validation & Linting**:
|
||||||
- Web UI: http://100.70.115.1:3000 (Tailscale only)
|
* Tests `server2/xray-config.json` for proper JSON syntax.
|
||||||
- DNS: 100.70.115.1:53
|
* Tests `server2/clash-meta.yaml` for correct YAML structural formatting.
|
||||||
- Login: admin / *(change default password!)*
|
* Downloads a static Caddy binary to format check (`caddy fmt --check`) and syntax validate (`caddy validate --adapter caddyfile`) the `caddy-vps/Caddyfile`.
|
||||||
- Tailscale DNS: set 100.70.115.1 as nameserver at https://login.tailscale.com/admin/dns
|
2. **Security Scan**:
|
||||||
- **IMPORTANT**: In Tailscale admin DNS settings, enable "Use with exit node" for this nameserver
|
* Verifies that no private keys or high-risk credentials have been accidentally committed to any text files in the repository.
|
||||||
and "Override DNS servers" to bypass GFW DNS poisoning
|
3. **SSH Deployments**:
|
||||||
|
* Deploys `xray-config.json` to `/usr/local/etc/xray/config.json` on `server2`, sets strict permissions (`600`), and restarts Xray.
|
||||||
## Exit Node Setup Notes
|
* Deploys `Caddyfile` to `/etc/caddy/Caddyfile` on `caddy-vps`, sets safe permissions (`644`), and performs a zero-downtime `systemctl reload caddy`.
|
||||||
- UFW forward policy must be `ACCEPT` (in `/etc/default/ufw`)
|
|
||||||
- NAT MASQUERADE rule for `ens3` added to `/etc/ufw/before.rules`
|
|
||||||
- Without these, Tailscale exit node traffic is silently dropped
|
|
||||||
|
|
||||||
## Services Running
|
|
||||||
- Xray (VLESS+Reality) on port 443
|
|
||||||
- Tailscale (exit node)
|
|
||||||
- WireGuard on port 51820
|
|
||||||
- AdGuard Home (DNS ad blocker)
|
|
||||||
- fail2ban (SSH protection)
|
|
||||||
|
|
||||||
## Security
|
|
||||||
- SSH: key-only auth, root login disabled
|
|
||||||
- UFW: only 22/tcp, 443/tcp (iptables), 51820/udp open
|
|
||||||
- fail2ban: active
|
|
||||||
- Old Clash Meta proxy: stopped and disabled
|
|
||||||
- nginx: stopped and disabled
|
|
||||||
- rpcbind: disabled
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
(security_headers) {
|
||||||
|
header {
|
||||||
|
X-Content-Type-Options nosniff
|
||||||
|
X-Frame-Options SAMEORIGIN
|
||||||
|
Referrer-Policy strict-origin-when-cross-origin
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
-Server
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(authelia) {
|
||||||
|
forward_auth 100.78.131.124:9092 {
|
||||||
|
uri /api/verify?rd=https://auth.jimmygan.com
|
||||||
|
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Authelia portal (no forward_auth on itself)
|
||||||
|
auth.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
reverse_proxy 100.78.131.124:9092
|
||||||
|
}
|
||||||
|
|
||||||
|
# Protected services
|
||||||
|
nas.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
import authelia
|
||||||
|
reverse_proxy 100.78.131.124:4000 {
|
||||||
|
header_up Host {host}
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-For {remote_host}
|
||||||
|
header_up X-Forwarded-Proto {scheme}
|
||||||
|
header_up X-Forwarded-Host {host}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dev.nas.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
import authelia
|
||||||
|
reverse_proxy 100.78.131.124:4001
|
||||||
|
}
|
||||||
|
|
||||||
|
music.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
import authelia
|
||||||
|
reverse_proxy 100.78.131.124:4533 {
|
||||||
|
flush_interval -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
photos.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
import authelia
|
||||||
|
reverse_proxy 100.78.131.124:2283 {
|
||||||
|
header_up X-Forwarded-Proto https
|
||||||
|
header_up X-Forwarded-Host {host}
|
||||||
|
transport http {
|
||||||
|
read_timeout 10m
|
||||||
|
write_timeout 10m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
photos-app.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
reverse_proxy 100.78.131.124:2283 {
|
||||||
|
header_up X-Forwarded-Proto https
|
||||||
|
header_up X-Forwarded-Host {host}
|
||||||
|
transport http {
|
||||||
|
read_timeout 10m
|
||||||
|
write_timeout 10m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
git.jimmygan.com {
|
||||||
|
import security_headers
|
||||||
|
import authelia
|
||||||
|
reverse_proxy 100.78.131.124:3300
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user