Offline-first photo capture app for Nextcloud with: - Camera capture with continuous mode (auto-reopens after each photo) - File browser with fullscreen image gallery, swipe navigation, and rename - Upload queue with background sync engine - Admin panel for Nextcloud user management - Service worker for offline-first caching (v13) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
337 lines
6.3 KiB
Markdown
337 lines
6.3 KiB
Markdown
# NextSnap Deployment Guide
|
|
|
|
This guide covers deploying NextSnap using Docker and Docker Compose.
|
|
|
|
## Prerequisites
|
|
|
|
- Docker 20.10 or later
|
|
- Docker Compose 2.0 or later
|
|
- A Nextcloud instance with admin access
|
|
- HTTPS setup (required for PWA features)
|
|
|
|
## Quick Start
|
|
|
|
### 1. Clone the Repository
|
|
|
|
```bash
|
|
git clone <repository-url>
|
|
cd nextsnap
|
|
```
|
|
|
|
### 2. Configure Environment Variables
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit `.env` and set your values:
|
|
|
|
```bash
|
|
# Generate a secure secret key
|
|
python -c "import secrets; print(secrets.token_hex(32))"
|
|
|
|
# Update .env with:
|
|
SECRET_KEY=<generated-key>
|
|
NEXTCLOUD_URL=https://your-nextcloud-instance.com
|
|
PORT=8000
|
|
TZ=America/New_York
|
|
```
|
|
|
|
### 3. Build and Run
|
|
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
The application will be available at `http://localhost:8000`
|
|
|
|
### 4. Verify Deployment
|
|
|
|
```bash
|
|
# Check container status
|
|
docker-compose ps
|
|
|
|
# Check logs
|
|
docker-compose logs -f nextsnap
|
|
|
|
# Test health endpoint
|
|
curl http://localhost:8000/api/health
|
|
```
|
|
|
|
## Production Deployment
|
|
|
|
### HTTPS Setup (Required)
|
|
|
|
NextSnap requires HTTPS for PWA features and secure cookies. Use a reverse proxy:
|
|
|
|
#### Option 1: Nginx
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name nextsnap.example.com;
|
|
|
|
ssl_certificate /path/to/cert.pem;
|
|
ssl_certificate_key /path/to/key.pem;
|
|
|
|
location / {
|
|
proxy_pass http://localhost:8000;
|
|
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;
|
|
|
|
# WebSocket support
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# Timeouts for large uploads
|
|
proxy_read_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
client_max_body_size 50M;
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Option 2: Caddy
|
|
|
|
```
|
|
nextsnap.example.com {
|
|
reverse_proxy localhost:8000
|
|
}
|
|
```
|
|
|
|
#### Option 3: Traefik
|
|
|
|
Update `docker-compose.yml`:
|
|
|
|
```yaml
|
|
services:
|
|
nextsnap:
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.nextsnap.rule=Host(`nextsnap.example.com`)"
|
|
- "traefik.http.routers.nextsnap.entrypoints=websecure"
|
|
- "traefik.http.routers.nextsnap.tls.certresolver=myresolver"
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Required | Default | Description |
|
|
|----------|----------|---------|-------------|
|
|
| `SECRET_KEY` | Yes | - | Flask secret key for sessions |
|
|
| `NEXTCLOUD_URL` | Yes | - | URL of your Nextcloud instance |
|
|
| `PORT` | No | 8000 | Port to expose the application |
|
|
| `TZ` | No | UTC | Container timezone |
|
|
| `FLASK_ENV` | No | production | Flask environment |
|
|
|
|
### Security Recommendations
|
|
|
|
1. **Use a Strong Secret Key**
|
|
```bash
|
|
python -c "import secrets; print(secrets.token_hex(32))"
|
|
```
|
|
|
|
2. **Enable HTTPS**
|
|
- Required for PWA installation
|
|
- Required for secure cookies
|
|
|
|
3. **Keep Docker Images Updated**
|
|
```bash
|
|
docker-compose pull
|
|
docker-compose up -d
|
|
```
|
|
|
|
4. **Restrict Network Access**
|
|
- Only expose port 8000 to reverse proxy
|
|
- Use firewall rules to limit access
|
|
|
|
5. **Monitor Logs**
|
|
```bash
|
|
docker-compose logs -f --tail=100 nextsnap
|
|
```
|
|
|
|
### Backup and Restore
|
|
|
|
#### Backup Session Data
|
|
|
|
```bash
|
|
# Create backup
|
|
docker run --rm -v nextsnap_flask_sessions:/data -v $(pwd):/backup \
|
|
alpine tar czf /backup/sessions_backup.tar.gz -C /data .
|
|
```
|
|
|
|
#### Restore Session Data
|
|
|
|
```bash
|
|
# Restore backup
|
|
docker run --rm -v nextsnap_flask_sessions:/data -v $(pwd):/backup \
|
|
alpine tar xzf /backup/sessions_backup.tar.gz -C /data
|
|
```
|
|
|
|
## Updating
|
|
|
|
### Pull Latest Changes
|
|
|
|
```bash
|
|
git pull origin main
|
|
```
|
|
|
|
### Rebuild and Restart
|
|
|
|
```bash
|
|
docker-compose down
|
|
docker-compose build --no-cache
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Check for Breaking Changes
|
|
|
|
Review `CHANGELOG.md` and update your `.env` if new variables are required.
|
|
|
|
## Troubleshooting
|
|
|
|
### Container Won't Start
|
|
|
|
```bash
|
|
# Check logs
|
|
docker-compose logs nextsnap
|
|
|
|
# Check environment variables
|
|
docker-compose config
|
|
```
|
|
|
|
### Connection to Nextcloud Fails
|
|
|
|
1. Verify `NEXTCLOUD_URL` is correct
|
|
2. Test Nextcloud connectivity:
|
|
```bash
|
|
curl -I https://your-nextcloud-instance.com
|
|
```
|
|
3. Check Nextcloud CORS settings
|
|
4. Verify user credentials
|
|
|
|
### PWA Not Installing
|
|
|
|
1. Ensure HTTPS is enabled
|
|
2. Check manifest is accessible: `https://your-domain.com/static/manifest.json`
|
|
3. Check service worker: `https://your-domain.com/static/sw.js`
|
|
4. Open browser DevTools → Application → Service Workers
|
|
|
|
### Session Issues
|
|
|
|
```bash
|
|
# Clear session data
|
|
docker-compose down
|
|
docker volume rm nextsnap_flask_sessions
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Large Upload Failures
|
|
|
|
1. Check `MAX_CONTENT_LENGTH` in `config.py` (default: 50MB)
|
|
2. Increase nginx/proxy timeout values
|
|
3. Check Nextcloud upload limits
|
|
|
|
## Performance Tuning
|
|
|
|
### Gunicorn Workers
|
|
|
|
Edit `Dockerfile` CMD to adjust workers:
|
|
|
|
```dockerfile
|
|
CMD ["gunicorn", \
|
|
"--workers", "8", \ # Increase for more traffic
|
|
"--bind", "0.0.0.0:8000", \
|
|
...
|
|
```
|
|
|
|
Rule of thumb: `workers = (2 * CPU_cores) + 1`
|
|
|
|
### Resource Limits
|
|
|
|
Add to `docker-compose.yml`:
|
|
|
|
```yaml
|
|
services:
|
|
nextsnap:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2'
|
|
memory: 1G
|
|
reservations:
|
|
cpus: '0.5'
|
|
memory: 256M
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
### Health Checks
|
|
|
|
```bash
|
|
# Built-in health endpoint
|
|
curl http://localhost:8000/api/health
|
|
|
|
# Container health status
|
|
docker inspect --format='{{.State.Health.Status}}' nextsnap
|
|
```
|
|
|
|
### Logs
|
|
|
|
```bash
|
|
# Follow logs
|
|
docker-compose logs -f nextsnap
|
|
|
|
# Last 100 lines
|
|
docker-compose logs --tail=100 nextsnap
|
|
|
|
# Filter by timestamp
|
|
docker-compose logs --since 30m nextsnap
|
|
```
|
|
|
|
### Metrics
|
|
|
|
Consider adding:
|
|
- Prometheus metrics
|
|
- Grafana dashboards
|
|
- Alert manager for errors
|
|
|
|
## Advanced Configuration
|
|
|
|
### Custom Port
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
ports:
|
|
- "3000:8000" # Expose on port 3000
|
|
```
|
|
|
|
### External Session Storage
|
|
|
|
For multi-instance deployments, consider Redis for sessions:
|
|
|
|
```python
|
|
# config.py
|
|
SESSION_TYPE = 'redis'
|
|
SESSION_REDIS = redis.from_url('redis://redis:6379')
|
|
```
|
|
|
|
### Development Mode
|
|
|
|
```bash
|
|
# Use development compose file
|
|
docker-compose -f docker-compose.dev.yml up
|
|
```
|
|
|
|
## Support
|
|
|
|
- GitHub Issues: <repository-url>/issues
|
|
- Documentation: README.md
|
|
- Nextcloud Docs: https://docs.nextcloud.com
|
|
|
|
## License
|
|
|
|
See LICENSE file for details.
|