Skip to content

Commit 683babf

Browse files
authored
Add some files to the test config folder, and a readme
1 parent 5308cc7 commit 683babf

4 files changed

Lines changed: 233 additions & 0 deletions

File tree

config/README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Configuration Secrets
2+
3+
This directory contains sensitive configuration files used as Docker secrets.
4+
5+
## Required Files
6+
7+
### `access.txt`
8+
Basic authentication credentials for LCP API access and JWT dashboard accounts.
9+
10+
**Format:**
11+
```
12+
username:password
13+
dashboard_user1:password1
14+
dashboard_user2:password2
15+
```
16+
17+
First line: Basic auth credentials for API access
18+
Following lines: Dashboard admin accounts (username:password pairs)
19+
20+
### `mysql-root-password.txt`
21+
MySQL root password.
22+
23+
**Example:**
24+
```
25+
your_strong_root_password_here
26+
```
27+
28+
### `mysql-password.txt`
29+
Password for the MySQL user defined in `MYSQL_USER` (typically `lcp_user`).
30+
31+
**Example:**
32+
```
33+
your_strong_user_password_here
34+
```
35+
36+
### `jwt-secretkey.txt`
37+
Secret key used to sign JWT tokens for dashboard authentication.
38+
39+
**Example:**
40+
```
41+
your_strong_random_jwt_secret_key_minimum_32_characters
42+
```
43+
44+
**⚠️ Important:** Generate a strong random key of at least 32 characters.
45+
46+
## Security Best Practices
47+
48+
1. **Never commit these files to version control** (already ignored in `.gitignore`)
49+
2. **Use strong, random passwords** - minimum 16 characters
50+
3. **Different passwords for each secret**
51+
4. **Generate JWT secret key with:**
52+
```bash
53+
openssl rand -base64 48
54+
```
55+
5. **Restrict file permissions:**
56+
```bash
57+
chmod 600 config/*.txt
58+
```
59+
6. **Rotate secrets regularly** in production
60+
7. **Backup secrets securely** (encrypted storage)
61+
62+
## Initial Setup
63+
64+
1. Copy example files or create new ones:
65+
```bash
66+
cd config/
67+
echo "your_mysql_root_password" > mysql-root-password.txt
68+
echo "your_mysql_user_password" > mysql-password.txt
69+
echo "apiuser:apipassword" > access.txt
70+
openssl rand -base64 48 > jwt-secretkey.txt
71+
chmod 600 *.txt
72+
```
73+
74+
2. Update `config-vm/` directory with production values if needed
75+
76+
## How Secrets Are Used
77+
78+
- **Docker Compose** mounts these files to `/run/secrets/` inside containers
79+
- **LCP Server** reads secrets at startup via environment variables:
80+
- `LCPSERVER_ACCESS_FILE``/run/secrets/access`
81+
- `MYSQL_PASSWORD_FILE``/run/secrets/mysql-password`
82+
- `JWT_SECRETKEY_FILE``/run/secrets/jwt-secretkey`
83+
- Passwords are **never** stored in environment variables or code

config/access.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
username:password
2+
bob:supersecret
3+
hugh:supersecret

config/jwt-secretkey.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
your_strong_jwt_secret_key_here_change_in_production

config/nginx.conf

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
events {
2+
worker_connections 1024;
3+
}
4+
5+
http {
6+
include /etc/nginx/mime.types;
7+
default_type application/octet-stream;
8+
9+
# Logging
10+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
11+
'$status $body_bytes_sent "$http_referer" '
12+
'"$http_user_agent" "$http_x_forwarded_for"';
13+
14+
access_log /var/log/nginx/access.log main;
15+
error_log /var/log/nginx/error.log;
16+
17+
# Gzip compression
18+
gzip on;
19+
gzip_vary on;
20+
gzip_min_length 1024;
21+
gzip_comp_level 6;
22+
gzip_types
23+
text/plain
24+
text/css
25+
text/xml
26+
text/javascript
27+
application/json
28+
application/javascript
29+
application/xml+rss
30+
application/atom+xml
31+
image/svg+xml;
32+
33+
# Rate limiting
34+
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
35+
36+
# Upstream for LCP server
37+
upstream lcp_server {
38+
server server:8989;
39+
keepalive 32;
40+
}
41+
42+
# Upstream for Dashboard service
43+
upstream lcp_dashboard {
44+
server dashboard:8080;
45+
keepalive 16;
46+
}
47+
48+
# HTTP configuration
49+
server {
50+
listen 80;
51+
server_name _;
52+
53+
# Security headers
54+
add_header X-Frame-Options "SAMEORIGIN" always;
55+
add_header X-Content-Type-Options "nosniff" always;
56+
add_header X-XSS-Protection "1; mode=block" always;
57+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
58+
59+
# Client max body size for file uploads
60+
client_max_body_size 100M;
61+
62+
# Proxy settings
63+
proxy_http_version 1.1;
64+
proxy_set_header Connection "";
65+
proxy_set_header Host $host;
66+
proxy_set_header X-Real-IP $remote_addr;
67+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
68+
proxy_set_header X-Forwarded-Proto $scheme;
69+
70+
# Health check endpoint
71+
location /health {
72+
access_log off;
73+
proxy_pass http://lcp_server/health;
74+
proxy_connect_timeout 5s;
75+
proxy_read_timeout 10s;
76+
}
77+
78+
# Group 1: Public / High Traffic (Status, Register, Renew, Return)
79+
# These endpoints are frequently accessed by devices
80+
location ~ ^/(status|register|renew|return)/ {
81+
limit_req zone=api burst=50 nodelay;
82+
proxy_pass http://lcp_server;
83+
proxy_connect_timeout 30s;
84+
proxy_read_timeout 60s;
85+
proxy_send_timeout 60s;
86+
}
87+
88+
# Group 2: LCP Server API (Publications, LicenseInfo, Licenses, Revoke, Dashdata)
89+
# These endpoints are protected by Basic Auth, for use by LCP integrators,
90+
# or (dashdata) protected by JWT, for use by the dashboard UI.
91+
location ~ ^/(publications|licenseinfo|licenses|revoke|dashdata)(?:/|$) {
92+
limit_req zone=api burst=20 nodelay;
93+
proxy_pass http://lcp_server;
94+
proxy_connect_timeout 30s;
95+
proxy_read_timeout 120s;
96+
proxy_send_timeout 60s;
97+
}
98+
99+
# Group 3: Resources (Static files)
100+
# Large files, high burst allowed for parallel downloads
101+
location /resources/ {
102+
limit_req zone=api burst=100 nodelay;
103+
proxy_pass http://lcp_server/resources/;
104+
proxy_connect_timeout 30s;
105+
proxy_read_timeout 300s; # Longer timeout for large files
106+
proxy_send_timeout 300s;
107+
}
108+
109+
# Group 4: Dashboard UI
110+
# Used by human admins via web interface
111+
# Access to the root and specific paths
112+
location ~ ^/($|login|dashboard|assets) {
113+
limit_req zone=api burst=20 nodelay;
114+
proxy_pass http://lcp_dashboard;
115+
proxy_connect_timeout 30s;
116+
proxy_read_timeout 60s;
117+
proxy_send_timeout 60s;
118+
# So the dashboard receives correct IP information
119+
proxy_set_header Host $host;
120+
proxy_set_header X-Real-IP $remote_addr;
121+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
122+
proxy_set_header X-Forwarded-Proto $scheme;
123+
}
124+
125+
# Group 4.1: Dashboard public assets
126+
location ~ ^/(favicon.ico|placeholder.svg|cleanup-localstorage.js)$ {
127+
limit_req zone=api burst=20 nodelay;
128+
proxy_pass http://lcp_dashboard;
129+
proxy_connect_timeout 30s;
130+
proxy_read_timeout 60s;
131+
proxy_send_timeout 60s;
132+
}
133+
134+
# Default proxy for all other requests (fallback)
135+
location / {
136+
return 404;
137+
access_log off;
138+
}
139+
140+
# Error pages
141+
error_page 502 503 504 /50x.html;
142+
location = /50x.html {
143+
root /usr/share/nginx/html;
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)