Add Scaleway Deployment Configuration #1
353
docs/SCALEWAY_DEPLOYMENT_DOCKER.md
Normal file
353
docs/SCALEWAY_DEPLOYMENT_DOCKER.md
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
# Alternative: Docker-based Deployment on Scaleway Instance
|
||||||
|
|
||||||
|
This guide provides an alternative deployment method using a Scaleway instance with Docker and Nginx.
|
||||||
|
|
||||||
|
## Advantages of this Method
|
||||||
|
|
||||||
|
- Full control over the web server
|
||||||
|
- Easy SSL/TLS setup with Let's Encrypt
|
||||||
|
- Better caching control
|
||||||
|
- Custom redirects and URL rewriting
|
||||||
|
- Lower egress costs for high-traffic sites
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Gitea → Build Hugo → Push to Scaleway Registry → Deploy to Instance via Docker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 1: Create Scaleway Instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scw instance server create \
|
||||||
|
name=notebook-server \
|
||||||
|
type=DEV1-S \
|
||||||
|
image=ubuntu_jammy \
|
||||||
|
zone=fr-par-1
|
||||||
|
```
|
||||||
|
|
||||||
|
Or via console: Create a DEV1-S instance with Ubuntu 22.04
|
||||||
|
|
||||||
|
## Step 2: Install Docker on Instance
|
||||||
|
|
||||||
|
SSH into your instance and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update system
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# Install Docker
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
|
||||||
|
# Install Docker Compose
|
||||||
|
sudo apt install docker-compose-plugin -y
|
||||||
|
|
||||||
|
# Install Nginx and Certbot
|
||||||
|
sudo apt install nginx certbot python3-certbot-nginx -y
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 3: Create Docker Deployment Structure
|
||||||
|
|
||||||
|
On your instance, create:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/notebook
|
||||||
|
cd /opt/notebook
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: notebook-nginx
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./public:/usr/share/nginx/html:ro
|
||||||
|
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
- ./ssl:/etc/nginx/ssl:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `nginx.conf`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name notebook.arnodo.fr;
|
||||||
|
|
||||||
|
# Redirect to HTTPS
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name notebook.arnodo.fr;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/ssl/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript
|
||||||
|
application/x-javascript application/xml+rss
|
||||||
|
application/javascript application/json;
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hugo pretty URLs
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ $uri.html =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom 404 page
|
||||||
|
error_page 404 /404.html;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 4: Configure DNS
|
||||||
|
|
||||||
|
Point your domain to the Scaleway instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
notebook.arnodo.fr A <INSTANCE_IP_ADDRESS>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 5: Setup SSL Certificate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo certbot certonly --standalone -d notebook.arnodo.fr
|
||||||
|
|
||||||
|
# Copy certificates to project directory
|
||||||
|
sudo cp /etc/letsencrypt/live/notebook.arnodo.fr/fullchain.pem /opt/notebook/ssl/
|
||||||
|
sudo cp /etc/letsencrypt/live/notebook.arnodo.fr/privkey.pem /opt/notebook/ssl/
|
||||||
|
sudo chown -R $USER:$USER /opt/notebook/ssl
|
||||||
|
```
|
||||||
|
|
||||||
|
Set up auto-renewal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add to crontab
|
||||||
|
0 0 1 * * certbot renew && cp /etc/letsencrypt/live/notebook.arnodo.fr/*.pem /opt/notebook/ssl/ && docker-compose -f /opt/notebook/docker-compose.yml restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 6: Update Gitea Workflow
|
||||||
|
|
||||||
|
Create `.gitea/workflows/deploy-docker.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Deploy to Scaleway Instance
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup Hugo
|
||||||
|
uses: peaceiris/actions-hugo@v2
|
||||||
|
with:
|
||||||
|
hugo-version: 'latest'
|
||||||
|
extended: true
|
||||||
|
|
||||||
|
- name: Build Hugo site
|
||||||
|
run: hugo --minify
|
||||||
|
|
||||||
|
- name: Install rsync
|
||||||
|
run: sudo apt-get install -y rsync
|
||||||
|
|
||||||
|
- name: Setup SSH key
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
ssh-keyscan -H ${{ secrets.SERVER_IP }} >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: Deploy to server
|
||||||
|
run: |
|
||||||
|
rsync -avz --delete \
|
||||||
|
-e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no" \
|
||||||
|
public/ \
|
||||||
|
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:/opt/notebook/public/
|
||||||
|
|
||||||
|
- name: Restart Nginx
|
||||||
|
run: |
|
||||||
|
ssh -i ~/.ssh/id_rsa ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} \
|
||||||
|
"cd /opt/notebook && docker-compose restart nginx"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 7: Configure Gitea Secrets
|
||||||
|
|
||||||
|
Add to repository secrets:
|
||||||
|
- `SSH_PRIVATE_KEY`: Your SSH private key for the instance
|
||||||
|
- `SERVER_IP`: Your Scaleway instance IP
|
||||||
|
- `SERVER_USER`: SSH user (usually `root` or `ubuntu`)
|
||||||
|
|
||||||
|
## Step 8: Create Deployment User (Recommended)
|
||||||
|
|
||||||
|
For better security, create a dedicated deployment user:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On the Scaleway instance
|
||||||
|
sudo useradd -m -s /bin/bash deployer
|
||||||
|
sudo usermod -aG docker deployer
|
||||||
|
sudo chown -R deployer:deployer /opt/notebook
|
||||||
|
|
||||||
|
# Generate SSH key on your local machine
|
||||||
|
ssh-keygen -t ed25519 -C "gitea-deployment" -f ~/.ssh/notebook_deploy
|
||||||
|
|
||||||
|
# Copy public key to instance
|
||||||
|
ssh-copy-id -i ~/.ssh/notebook_deploy.pub deployer@<instance-ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update the workflow to use `deployer` user.
|
||||||
|
|
||||||
|
## Cost Analysis
|
||||||
|
|
||||||
|
### Monthly Costs:
|
||||||
|
- **DEV1-S Instance**: ~€7-10/month
|
||||||
|
- **100 GB outbound traffic**: Included
|
||||||
|
- **Additional traffic**: €0.01/GB
|
||||||
|
- **Total**: ~€10/month for typical blog traffic
|
||||||
|
|
||||||
|
### Comparison with Object Storage:
|
||||||
|
- **More predictable costs**
|
||||||
|
- Better for high-traffic sites
|
||||||
|
- More control over caching and optimization
|
||||||
|
- Easier SSL/TLS management
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
Install monitoring tools:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install Prometheus Node Exporter
|
||||||
|
docker run -d \
|
||||||
|
--name=node-exporter \
|
||||||
|
--net="host" \
|
||||||
|
--pid="host" \
|
||||||
|
-v "/:/host:ro,rslave" \
|
||||||
|
quay.io/prometheus/node-exporter:latest \
|
||||||
|
--path.rootfs=/host
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use Scaleway monitoring (free):
|
||||||
|
- Enable in console under Instance → Monitoring
|
||||||
|
- Set up alerts for CPU, memory, disk usage
|
||||||
|
|
||||||
|
## Backup Strategy
|
||||||
|
|
||||||
|
1. **Automated backups**:
|
||||||
|
```bash
|
||||||
|
# Add to crontab
|
||||||
|
0 2 * * * tar -czf /backup/notebook-$(date +\%Y\%m\%d).tar.gz /opt/notebook
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use Scaleway snapshots**:
|
||||||
|
```bash
|
||||||
|
scw instance snapshot create volume-id=<volume-id> name=notebook-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Hardening
|
||||||
|
|
||||||
|
1. **Configure firewall**:
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 22/tcp
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
sudo ufw enable
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Disable password authentication**:
|
||||||
|
Edit `/etc/ssh/sshd_config`:
|
||||||
|
```
|
||||||
|
PasswordAuthentication no
|
||||||
|
PubkeyAuthentication yes
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Keep system updated**:
|
||||||
|
```bash
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Install fail2ban**:
|
||||||
|
```bash
|
||||||
|
sudo apt install fail2ban -y
|
||||||
|
sudo systemctl enable fail2ban
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check logs:
|
||||||
|
```bash
|
||||||
|
docker-compose -f /opt/notebook/docker-compose.yml logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Nginx config:
|
||||||
|
```bash
|
||||||
|
docker-compose exec nginx nginx -t
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check SSL certificate:
|
||||||
|
```bash
|
||||||
|
openssl s_client -connect notebook.arnodo.fr:443 -servername notebook.arnodo.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
Add to `nginx.conf`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# HTTP/2 Server Push
|
||||||
|
http2_push_preload on;
|
||||||
|
|
||||||
|
# Connection optimization
|
||||||
|
keepalive_timeout 65;
|
||||||
|
keepalive_requests 100;
|
||||||
|
|
||||||
|
# Buffer sizes
|
||||||
|
client_body_buffer_size 128k;
|
||||||
|
client_max_body_size 10m;
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable Brotli compression (optional):
|
||||||
|
```bash
|
||||||
|
# Add Brotli module to nginx container
|
||||||
|
# Or use a pre-built image with Brotli support
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This Docker-based approach gives you more control and can be more cost-effective for sites with consistent traffic patterns.
|
||||||
Reference in New Issue
Block a user