Add comprehensive documentation in docs/ directory
docs/deployment.md: - Complete deployment guide for both automated and manual setup - Step-by-step instructions for Debian 12 ARM64 - Custom Caddy build with rate limiting plugin - Service configuration and security setup - Troubleshooting and maintenance sections - Performance tuning recommendations docs/api.md: - Comprehensive API documentation with examples - All public and admin endpoints documented - Request/response schemas and validation rules - Authentication flows and error handling - Rate limiting and security feature documentation - Client library examples (JavaScript, curl) Fixes README.md reference to non-existent docs/deployment.md. Both files provide detailed technical documentation for: - Deployment procedures and requirements - API usage and integration - Security features and limitations - Troubleshooting and maintenance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1918217449
commit
5176636f6d
2 changed files with 652 additions and 0 deletions
305
docs/api.md
Normal file
305
docs/api.md
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
# Great Lakes Ice Report - API Documentation
|
||||||
|
|
||||||
|
This document provides an overview of the API endpoints. For interactive documentation with examples, visit `/api-docs` when the server is running.
|
||||||
|
|
||||||
|
## Base URL
|
||||||
|
|
||||||
|
- **Development**: `http://localhost:3000`
|
||||||
|
- **Production**: `https://your-domain.com`
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Admin endpoints require Bearer token authentication:
|
||||||
|
```
|
||||||
|
Authorization: Bearer YOUR_TOKEN_HERE
|
||||||
|
```
|
||||||
|
|
||||||
|
Get a token by authenticating with the admin password at `POST /api/admin/login`.
|
||||||
|
|
||||||
|
## Rate Limiting
|
||||||
|
|
||||||
|
- **General API**: 30 requests per minute per IP
|
||||||
|
- **Location Submissions**: 10 requests per 15 minutes per IP
|
||||||
|
|
||||||
|
## Public Endpoints
|
||||||
|
|
||||||
|
### Get Configuration
|
||||||
|
```http
|
||||||
|
GET /api/config
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns MapBox API configuration for frontend geocoding.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mapboxAccessToken": "pk.your_token_here",
|
||||||
|
"hasMapbox": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Active Locations
|
||||||
|
```http
|
||||||
|
GET /api/locations
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all active location reports (less than 48 hours old or marked persistent).
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 123,
|
||||||
|
"address": "Main St & Oak Ave, Grand Rapids, MI",
|
||||||
|
"latitude": 42.9634,
|
||||||
|
"longitude": -85.6681,
|
||||||
|
"description": "Black ice present, multiple vehicles stuck",
|
||||||
|
"persistent": false,
|
||||||
|
"created_at": "2025-01-15T10:30:00.000Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Submit Location Report
|
||||||
|
```http
|
||||||
|
POST /api/locations
|
||||||
|
```
|
||||||
|
|
||||||
|
Submit a new ice condition report with automatic profanity filtering.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"address": "Main St & Oak Ave, Grand Rapids, MI",
|
||||||
|
"latitude": 42.9634,
|
||||||
|
"longitude": -85.6681,
|
||||||
|
"description": "Black ice spotted, drive carefully"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Validation:**
|
||||||
|
- `address`: Required, max 500 characters
|
||||||
|
- `latitude`: Optional, valid number
|
||||||
|
- `longitude`: Optional, valid number
|
||||||
|
- `description`: Optional, max 1000 characters
|
||||||
|
|
||||||
|
**Response (Success):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 125,
|
||||||
|
"address": "Main St & Oak Ave, Grand Rapids, MI",
|
||||||
|
"latitude": 42.9634,
|
||||||
|
"longitude": -85.6681,
|
||||||
|
"description": "Black ice spotted, drive carefully",
|
||||||
|
"persistent": false,
|
||||||
|
"created_at": "2025-01-15T12:00:00.000Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response (Profanity Detected):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Submission rejected",
|
||||||
|
"message": "Your description contains inappropriate language...",
|
||||||
|
"details": {
|
||||||
|
"severity": "medium",
|
||||||
|
"wordCount": 1,
|
||||||
|
"detectedCategories": ["general"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Admin Endpoints
|
||||||
|
|
||||||
|
All admin endpoints require authentication via `Authorization: Bearer <token>`.
|
||||||
|
|
||||||
|
### Admin Login
|
||||||
|
```http
|
||||||
|
POST /api/admin/login
|
||||||
|
```
|
||||||
|
|
||||||
|
Authenticate with admin password to receive access token.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"password": "your_admin_password"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"token": "your_bearer_token_here",
|
||||||
|
"message": "Login successful"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get All Locations
|
||||||
|
```http
|
||||||
|
GET /api/admin/locations
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all location reports including expired ones.
|
||||||
|
|
||||||
|
### Update Location
|
||||||
|
```http
|
||||||
|
PUT /api/admin/locations/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
Update location details.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"address": "Updated Address",
|
||||||
|
"latitude": 42.9634,
|
||||||
|
"longitude": -85.6681,
|
||||||
|
"description": "Updated description"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Toggle Persistent Status
|
||||||
|
```http
|
||||||
|
PATCH /api/admin/locations/:id/persistent
|
||||||
|
```
|
||||||
|
|
||||||
|
Mark location as persistent (won't auto-expire) or remove persistent status.
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"persistent": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete Location
|
||||||
|
```http
|
||||||
|
DELETE /api/admin/locations/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
Permanently delete a location report.
|
||||||
|
|
||||||
|
### Profanity Word Management
|
||||||
|
|
||||||
|
#### Get All Profanity Words
|
||||||
|
```http
|
||||||
|
GET /api/admin/profanity-words
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add Profanity Word
|
||||||
|
```http
|
||||||
|
POST /api/admin/profanity-words
|
||||||
|
```
|
||||||
|
|
||||||
|
**Request Body:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"word": "badword",
|
||||||
|
"severity": "medium",
|
||||||
|
"category": "custom"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Update Profanity Word
|
||||||
|
```http
|
||||||
|
PUT /api/admin/profanity-words/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Delete Profanity Word
|
||||||
|
```http
|
||||||
|
DELETE /api/admin/profanity-words/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Responses
|
||||||
|
|
||||||
|
### Rate Limiting
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Too many location reports submitted",
|
||||||
|
"message": "You can submit up to 10 location reports every 15 minutes. Please wait before submitting more.",
|
||||||
|
"retryAfter": "15 minutes"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Validation Errors
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Address must be a string with maximum 500 characters"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentication Errors
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Access denied"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Not Found
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Location not found"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server Errors
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Internal server error"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interactive Documentation
|
||||||
|
|
||||||
|
For complete interactive API documentation with live testing capabilities, visit `/api-docs` when running the server. This provides:
|
||||||
|
|
||||||
|
- Complete endpoint specifications
|
||||||
|
- Request/response schemas
|
||||||
|
- Interactive testing interface
|
||||||
|
- Authentication flows
|
||||||
|
- Example requests and responses
|
||||||
|
|
||||||
|
## Security Features
|
||||||
|
|
||||||
|
- **Rate Limiting**: Prevents abuse and DoS attacks
|
||||||
|
- **Input Validation**: Strict length and type checking
|
||||||
|
- **Profanity Filtering**: Automatic content moderation
|
||||||
|
- **Authentication**: Secure admin access with bearer tokens
|
||||||
|
- **HTTPS**: SSL/TLS encryption in production
|
||||||
|
- **Audit Logging**: Suspicious activity detection
|
||||||
|
|
||||||
|
## Client Libraries
|
||||||
|
|
||||||
|
The API follows REST conventions and can be consumed by any HTTP client. Examples:
|
||||||
|
|
||||||
|
### JavaScript/Node.js
|
||||||
|
```javascript
|
||||||
|
// Submit location report
|
||||||
|
const response = await fetch('/api/locations', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
address: 'Main St & Oak Ave',
|
||||||
|
description: 'Icy conditions'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### curl
|
||||||
|
```bash
|
||||||
|
# Get active locations
|
||||||
|
curl https://your-domain.com/api/locations
|
||||||
|
|
||||||
|
# Submit location report
|
||||||
|
curl -X POST https://your-domain.com/api/locations \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"address":"Main St & Oak Ave","description":"Icy conditions"}'
|
||||||
|
|
||||||
|
# Admin login
|
||||||
|
curl -X POST https://your-domain.com/api/admin/login \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"password":"your_password"}'
|
||||||
|
```
|
347
docs/deployment.md
Normal file
347
docs/deployment.md
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
# Great Lakes Ice Report - Deployment Guide
|
||||||
|
|
||||||
|
This guide covers both automated and manual deployment options for the Great Lakes Ice Report application.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **Server**: Debian 12 ARM64 (or compatible Linux distribution)
|
||||||
|
- **Node.js**: Version 18 or higher
|
||||||
|
- **Domain**: DNS pointing to your server
|
||||||
|
- **Ports**: 80 and 443 open for web traffic
|
||||||
|
|
||||||
|
## Automated Deployment (Recommended)
|
||||||
|
|
||||||
|
### Quick Start
|
||||||
|
|
||||||
|
1. **Run the deployment script on your server:**
|
||||||
|
```bash
|
||||||
|
curl -sSL https://ice-puremichigan-lol.s3.amazonaws.com/scripts/deploy.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Clone and setup the application:**
|
||||||
|
```bash
|
||||||
|
git clone git@git.deco.sh:deco/ice.git /opt/ice
|
||||||
|
cd /opt/ice
|
||||||
|
npm install # This automatically builds CSS via postinstall
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Configure environment variables:**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env # Add your API keys
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Start services:**
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable ice
|
||||||
|
sudo systemctl start ice
|
||||||
|
sudo systemctl enable caddy
|
||||||
|
sudo systemctl start caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
### What the Automated Script Does
|
||||||
|
|
||||||
|
The deployment script automatically:
|
||||||
|
|
||||||
|
1. **System Updates**: Updates package repositories and system packages
|
||||||
|
2. **Node.js Installation**: Installs Node.js 20.x with build tools
|
||||||
|
3. **Go Installation**: Installs Go (required for building Caddy with plugins)
|
||||||
|
4. **Custom Caddy Build**: Builds Caddy with rate limiting plugin using xcaddy
|
||||||
|
5. **Service Configuration**: Creates systemd services for both the app and Caddy
|
||||||
|
6. **Security Setup**: Configures users, permissions, and security settings
|
||||||
|
|
||||||
|
## Manual Deployment
|
||||||
|
|
||||||
|
### 1. System Preparation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update system
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# Install Node.js 20.x
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||||
|
sudo apt install -y nodejs build-essential
|
||||||
|
|
||||||
|
# Install Git (if not already installed)
|
||||||
|
sudo apt install -y git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Install Go (for Custom Caddy)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download and install Go
|
||||||
|
wget -q https://go.dev/dl/go1.21.5.linux-arm64.tar.gz
|
||||||
|
sudo rm -rf /usr/local/go
|
||||||
|
sudo tar -C /usr/local -xzf go1.21.5.linux-arm64.tar.gz
|
||||||
|
|
||||||
|
# Add to PATH
|
||||||
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
|
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Build Custom Caddy with Rate Limiting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install xcaddy
|
||||||
|
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
|
||||||
|
export PATH=$PATH:$(go env GOPATH)/bin
|
||||||
|
|
||||||
|
# Build Caddy with rate limiting plugin
|
||||||
|
xcaddy build --with github.com/mholt/caddy-ratelimit
|
||||||
|
|
||||||
|
# Install Caddy
|
||||||
|
sudo mv caddy /usr/local/bin/caddy
|
||||||
|
sudo chmod +x /usr/local/bin/caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Create Users and Directories
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create Caddy user
|
||||||
|
sudo groupadd --system caddy
|
||||||
|
sudo useradd --system --gid caddy --create-home --home-dir /var/lib/caddy --shell /usr/sbin/nologin caddy
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
sudo mkdir -p /etc/caddy /var/log/caddy
|
||||||
|
sudo chown -R caddy:caddy /var/log/caddy
|
||||||
|
|
||||||
|
# Create app user
|
||||||
|
sudo groupadd --system great-lakes-ice-report
|
||||||
|
sudo useradd --system --gid great-lakes-ice-report --create-home --home-dir /opt/great-lakes-ice-report --shell /usr/sbin/nologin great-lakes-ice-report
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Deploy Application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone repository
|
||||||
|
sudo git clone https://github.com/your-username/ice.git /opt/great-lakes-ice-report
|
||||||
|
cd /opt/great-lakes-ice-report
|
||||||
|
|
||||||
|
# Install dependencies and build
|
||||||
|
sudo npm install
|
||||||
|
sudo npm run build
|
||||||
|
|
||||||
|
# Set ownership
|
||||||
|
sudo chown -R great-lakes-ice-report:great-lakes-ice-report /opt/great-lakes-ice-report
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Configure Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy environment template
|
||||||
|
sudo cp .env.example .env
|
||||||
|
|
||||||
|
# Edit environment file
|
||||||
|
sudo nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
**Required environment variables:**
|
||||||
|
```bash
|
||||||
|
# MapBox API token (get free token at https://account.mapbox.com/access-tokens/)
|
||||||
|
MAPBOX_ACCESS_TOKEN=pk.your_mapbox_token_here
|
||||||
|
|
||||||
|
# Admin panel password
|
||||||
|
ADMIN_PASSWORD=your_secure_password
|
||||||
|
|
||||||
|
# Server port (default: 3000)
|
||||||
|
PORT=3000
|
||||||
|
|
||||||
|
# Node environment
|
||||||
|
NODE_ENV=production
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Configure Systemd Services
|
||||||
|
|
||||||
|
**Create app service:**
|
||||||
|
```bash
|
||||||
|
sudo cp scripts/great-lakes-ice-report.service /etc/systemd/system/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create Caddy service:**
|
||||||
|
```bash
|
||||||
|
sudo tee /etc/systemd/system/caddy.service > /dev/null <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Caddy
|
||||||
|
Documentation=https://caddyserver.com/docs/
|
||||||
|
After=network.target network-online.target
|
||||||
|
Requires=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
User=caddy
|
||||||
|
Group=caddy
|
||||||
|
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile
|
||||||
|
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
|
||||||
|
TimeoutStopSec=5s
|
||||||
|
LimitNOFILE=1048576
|
||||||
|
LimitNPROC=1048576
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectSystem=full
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Configure Caddy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy Caddyfile
|
||||||
|
sudo cp scripts/Caddyfile /etc/caddy/
|
||||||
|
|
||||||
|
# Edit domain name in Caddyfile
|
||||||
|
sudo nano /etc/caddy/Caddyfile
|
||||||
|
# Change 'ice.puremichigan.lol' to your domain
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9. Start Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Reload systemd
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
|
||||||
|
# Enable and start services
|
||||||
|
sudo systemctl enable great-lakes-ice-report
|
||||||
|
sudo systemctl start great-lakes-ice-report
|
||||||
|
|
||||||
|
sudo systemctl enable caddy
|
||||||
|
sudo systemctl start caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Configuration
|
||||||
|
|
||||||
|
### Firewall Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install UFW if not present
|
||||||
|
sudo apt install -y ufw
|
||||||
|
|
||||||
|
# Configure firewall
|
||||||
|
sudo ufw default deny incoming
|
||||||
|
sudo ufw default allow outgoing
|
||||||
|
sudo ufw allow ssh
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
sudo ufw --force enable
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSL Certificates
|
||||||
|
|
||||||
|
Caddy automatically obtains SSL certificates from Let's Encrypt. No manual configuration required.
|
||||||
|
|
||||||
|
### Rate Limiting
|
||||||
|
|
||||||
|
The application includes multiple layers of rate limiting:
|
||||||
|
|
||||||
|
1. **Application Level**: 10 requests per 15 minutes per IP for location submissions
|
||||||
|
2. **Caddy Level**:
|
||||||
|
- 30 requests per minute for general API endpoints
|
||||||
|
- 5 requests per minute for location submissions
|
||||||
|
|
||||||
|
## Monitoring and Maintenance
|
||||||
|
|
||||||
|
### Service Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check application status
|
||||||
|
sudo systemctl status great-lakes-ice-report
|
||||||
|
|
||||||
|
# Check Caddy status
|
||||||
|
sudo systemctl status caddy
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
sudo journalctl -u great-lakes-ice-report -f
|
||||||
|
sudo journalctl -u caddy -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log Files
|
||||||
|
|
||||||
|
- **Application logs**: `sudo journalctl -u great-lakes-ice-report`
|
||||||
|
- **Caddy access logs**: `/var/log/caddy/great-lakes-ice-report.log`
|
||||||
|
- **System logs**: `/var/log/syslog`
|
||||||
|
|
||||||
|
### Database Maintenance
|
||||||
|
|
||||||
|
The application automatically:
|
||||||
|
- Cleans up expired location reports (older than 48 hours)
|
||||||
|
- Maintains profanity filter database
|
||||||
|
- Uses SQLite with automatic cleanup
|
||||||
|
|
||||||
|
### Updates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to app directory
|
||||||
|
cd /opt/great-lakes-ice-report
|
||||||
|
|
||||||
|
# Pull latest changes
|
||||||
|
sudo git pull
|
||||||
|
|
||||||
|
# Install new dependencies
|
||||||
|
sudo npm install
|
||||||
|
|
||||||
|
# Rebuild application
|
||||||
|
sudo npm run build
|
||||||
|
|
||||||
|
# Restart service
|
||||||
|
sudo systemctl restart great-lakes-ice-report
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Service won't start**:
|
||||||
|
```bash
|
||||||
|
sudo journalctl -u great-lakes-ice-report --no-pager
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **SSL certificate issues**:
|
||||||
|
```bash
|
||||||
|
sudo journalctl -u caddy --no-pager
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Database permissions**:
|
||||||
|
```bash
|
||||||
|
sudo chown -R great-lakes-ice-report:great-lakes-ice-report /opt/great-lakes-ice-report
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Port conflicts**:
|
||||||
|
```bash
|
||||||
|
sudo netstat -tlnp | grep :3000
|
||||||
|
sudo netstat -tlnp | grep :80
|
||||||
|
sudo netstat -tlnp | grep :443
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Tuning
|
||||||
|
|
||||||
|
For high-traffic deployments:
|
||||||
|
|
||||||
|
1. **Increase Node.js memory limit**:
|
||||||
|
```bash
|
||||||
|
# Edit service file
|
||||||
|
sudo nano /etc/systemd/system/great-lakes-ice-report.service
|
||||||
|
# Add: Environment=NODE_OPTIONS="--max-old-space-size=4096"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure log rotation**:
|
||||||
|
```bash
|
||||||
|
sudo nano /etc/logrotate.d/great-lakes-ice-report
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Monitor resource usage**:
|
||||||
|
```bash
|
||||||
|
htop
|
||||||
|
sudo iotop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For deployment issues:
|
||||||
|
- Check system logs: `sudo journalctl -f`
|
||||||
|
- Verify environment variables: `sudo -u great-lakes-ice-report env`
|
||||||
|
- Test application directly: `cd /opt/great-lakes-ice-report && sudo -u great-lakes-ice-report node server.js`
|
||||||
|
- Review this documentation and configuration files
|
||||||
|
|
||||||
|
The application includes comprehensive logging and monitoring to help diagnose issues quickly.
|
Loading…
Add table
Add a link
Reference in a new issue