Fix port conflict: separate Next.js (3001) from Go API (PORT)
- Next.js admin now runs on internal port 3001 - Go API uses Dokku's PORT environment variable (5000) - Updated admin proxy default to localhost:3001 - Added /_next/* static asset proxy route This fixes the "address already in use" error when deploying to Dokku where both services were trying to bind to port 3000. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -10,12 +10,12 @@ This guide provides step-by-step instructions for deploying the Casera Go API to
|
|||||||
4. [Create the App](#create-the-app)
|
4. [Create the App](#create-the-app)
|
||||||
5. [Configure PostgreSQL](#configure-postgresql)
|
5. [Configure PostgreSQL](#configure-postgresql)
|
||||||
6. [Configure Redis](#configure-redis)
|
6. [Configure Redis](#configure-redis)
|
||||||
7. [Configure Gorush (Push Notifications)](#configure-gorush-push-notifications)
|
7. [Set Environment Variables](#set-environment-variables)
|
||||||
8. [Set Environment Variables](#set-environment-variables)
|
8. [Configure Storage](#configure-storage)
|
||||||
9. [Configure Storage](#configure-storage)
|
9. [Deploy the Application](#deploy-the-application)
|
||||||
10. [Deploy the Application](#deploy-the-application)
|
10. [Configure SSL](#configure-ssl)
|
||||||
11. [Configure SSL](#configure-ssl)
|
11. [Set Up Worker Process](#set-up-worker-process)
|
||||||
12. [Set Up Worker Process](#set-up-worker-process)
|
12. [Push Notifications (Optional)](#push-notifications-optional)
|
||||||
13. [Maintenance Commands](#maintenance-commands)
|
13. [Maintenance Commands](#maintenance-commands)
|
||||||
14. [Troubleshooting](#troubleshooting)
|
14. [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
@@ -198,85 +198,6 @@ dokku redis:info casera-redis
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Configure Gorush (Push Notifications)
|
|
||||||
|
|
||||||
Gorush handles push notifications for iOS (APNs) and Android (FCM).
|
|
||||||
|
|
||||||
### 1. Create Gorush App
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dokku apps:create gorush
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Create Certificate Storage Directory
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create directory on server
|
|
||||||
mkdir -p /var/lib/dokku/data/storage/gorush/certs
|
|
||||||
|
|
||||||
# Set permissions (Dokku container user)
|
|
||||||
chown -R 32767:32767 /var/lib/dokku/data/storage/gorush
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Copy APNs Key to Server
|
|
||||||
|
|
||||||
From your **local machine**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
scp /path/to/AuthKey_XXXXXX.p8 root@your-server:/var/lib/dokku/data/storage/gorush/certs/apns_key.p8
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Mount Certificate Directory
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dokku storage:mount gorush /var/lib/dokku/data/storage/gorush/certs:/certs:ro
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Deploy Gorush
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dokku git:from-image gorush appleboy/gorush:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Configure Gorush Environment
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dokku config:set gorush \
|
|
||||||
GORUSH_CORE_PORT=8080 \
|
|
||||||
GORUSH_IOS_ENABLED=true \
|
|
||||||
GORUSH_IOS_KEY_PATH=/certs/apns_key.p8 \
|
|
||||||
GORUSH_IOS_KEY_ID=XXXXXXXXXX \
|
|
||||||
GORUSH_IOS_TEAM_ID=XXXXXXXXXX \
|
|
||||||
GORUSH_IOS_TOPIC=com.yourcompany.casera \
|
|
||||||
GORUSH_IOS_PRODUCTION=true \
|
|
||||||
GORUSH_ANDROID_ENABLED=true \
|
|
||||||
GORUSH_ANDROID_APIKEY=your-firebase-server-key
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Set Proxy Port
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dokku proxy:ports-set gorush http:80:8080
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Restart Gorush
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dokku ps:restart gorush
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Verify Gorush is Running
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check status
|
|
||||||
dokku ps:report gorush
|
|
||||||
|
|
||||||
# Check logs
|
|
||||||
dokku logs gorush
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Set Environment Variables
|
## Set Environment Variables
|
||||||
|
|
||||||
### 1. Required Variables
|
### 1. Required Variables
|
||||||
@@ -310,14 +231,30 @@ dokku config:set casera-api \
|
|||||||
APPLE_TEAM_ID=V3PF3M6B6U
|
APPLE_TEAM_ID=V3PF3M6B6U
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Admin Panel URL
|
### 4. Push Notifications (Optional)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dokku config:set casera-api \
|
||||||
|
GORUSH_CORE_PORT=8080 \
|
||||||
|
GORUSH_IOS_ENABLED=true \
|
||||||
|
GORUSH_IOS_KEY_PATH=/push_certs/AuthKey_R9N3SM2WD5.p8 \
|
||||||
|
GORUSH_IOS_KEY_ID=R9N3SM2WD5 \
|
||||||
|
GORUSH_IOS_TEAM_ID=V3PF3M6B6U \
|
||||||
|
GORUSH_IOS_TOPIC=com.tt.casera.CaseraDev \
|
||||||
|
GORUSH_IOS_PRODUCTION=true \
|
||||||
|
GORUSH_ANDROID_ENABLED=false
|
||||||
|
|
||||||
|
```
|
||||||
|
// GORUSH_ANDROID_APIKEY=your-firebase-server-key
|
||||||
|
|
||||||
|
### 5. Admin Panel URL
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dokku config:set casera-api \
|
dokku config:set casera-api \
|
||||||
NEXT_PUBLIC_API_URL=https://api.casera.treytartt.com
|
NEXT_PUBLIC_API_URL=https://api.casera.treytartt.com
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. View All Configuration
|
### 6. View All Configuration
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dokku config:show casera-api
|
dokku config:show casera-api
|
||||||
@@ -343,22 +280,6 @@ chown -R 32767:32767 /var/lib/dokku/data/storage/casera-api
|
|||||||
dokku storage:mount casera-api /var/lib/dokku/data/storage/casera-api/uploads:/app/uploads
|
dokku storage:mount casera-api /var/lib/dokku/data/storage/casera-api/uploads:/app/uploads
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. For Push Notification Certificates
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create certs directory
|
|
||||||
mkdir -p /var/lib/dokku/data/storage/casera-api/certs
|
|
||||||
|
|
||||||
# Copy your APNs key file
|
|
||||||
scp /local/path/to/AuthKey_XXXXXX.p8 root@your-server:/var/lib/dokku/data/storage/casera-api/certs/apns_key.p8
|
|
||||||
|
|
||||||
# Mount certs directory
|
|
||||||
dokku storage:mount casera-api /var/lib/dokku/data/storage/casera-api/certs:/certs:ro
|
|
||||||
|
|
||||||
# Set the path in config
|
|
||||||
dokku config:set casera-api APNS_AUTH_KEY_PATH=/certs/apns_key.p8
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deploy the Application
|
## Deploy the Application
|
||||||
@@ -445,6 +366,43 @@ dokku ps:report casera-api
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 7. Set Proxy Port
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dokku proxy:ports-set gorush http:80:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8. Restart Gorush
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dokku ps:restart gorush
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 9. Configure Casera API to Use Gorush
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dokku config:set casera-api GORUSH_URL=http://gorush.web:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 10. Verify Gorush is Running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
dokku ps:report gorush
|
||||||
|
|
||||||
|
# Check logs
|
||||||
|
dokku logs gorush
|
||||||
|
|
||||||
|
# Test health endpoint (if you have a domain set)
|
||||||
|
curl http://gorush.yourdomain.com/api/stat/go
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option B: Use External Push Service
|
||||||
|
|
||||||
|
Configure the app to use an external push notification service instead.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Maintenance Commands
|
## Maintenance Commands
|
||||||
|
|
||||||
### View Logs
|
### View Logs
|
||||||
|
|||||||
@@ -359,10 +359,11 @@ func SetupRoutes(router *gin.Engine, db *gorm.DB, cfg *config.Config, deps *Depe
|
|||||||
|
|
||||||
// setupAdminProxy configures reverse proxy to the Next.js admin panel
|
// setupAdminProxy configures reverse proxy to the Next.js admin panel
|
||||||
func setupAdminProxy(router *gin.Engine) {
|
func setupAdminProxy(router *gin.Engine) {
|
||||||
// Get admin panel URL from env, default to localhost:3000
|
// Get admin panel URL from env, default to localhost:3001
|
||||||
|
// Note: In production (Dokku), Next.js runs on internal port 3001
|
||||||
adminURL := os.Getenv("ADMIN_PANEL_URL")
|
adminURL := os.Getenv("ADMIN_PANEL_URL")
|
||||||
if adminURL == "" {
|
if adminURL == "" {
|
||||||
adminURL = "http://127.0.0.1:3000"
|
adminURL = "http://127.0.0.1:3001"
|
||||||
}
|
}
|
||||||
|
|
||||||
target, err := url.Parse(adminURL)
|
target, err := url.Parse(adminURL)
|
||||||
@@ -381,4 +382,9 @@ func setupAdminProxy(router *gin.Engine) {
|
|||||||
router.Any("/admin", func(c *gin.Context) {
|
router.Any("/admin", func(c *gin.Context) {
|
||||||
c.Redirect(http.StatusMovedPermanently, "/admin/")
|
c.Redirect(http.StatusMovedPermanently, "/admin/")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Proxy Next.js static assets
|
||||||
|
router.Any("/_next/*filepath", func(c *gin.Context) {
|
||||||
|
proxy.ServeHTTP(c.Writer, c.Request)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
12
start.sh
12
start.sh
@@ -11,8 +11,12 @@ if [ ! -f server.js ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Starting Next.js admin on :3000..."
|
# Save the main PORT for Go API (Dokku sets this)
|
||||||
HOSTNAME="0.0.0.0" PORT=3000 NODE_ENV=production node server.js &
|
API_PORT="${PORT:-5000}"
|
||||||
|
|
||||||
|
# Start Next.js admin on internal port 3001
|
||||||
|
echo "Starting Next.js admin on :3001..."
|
||||||
|
HOSTNAME="0.0.0.0" PORT=3001 NODE_ENV=production node server.js &
|
||||||
NODE_PID=$!
|
NODE_PID=$!
|
||||||
|
|
||||||
# Give Next.js a moment to boot
|
# Give Next.js a moment to boot
|
||||||
@@ -24,5 +28,7 @@ if ! kill -0 "$NODE_PID" 2>/dev/null; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Starting Go API on :${PORT:-5000}..."
|
# Start Go API on main PORT that Dokku expects
|
||||||
|
echo "Starting Go API on :${API_PORT}..."
|
||||||
|
export PORT="${API_PORT}"
|
||||||
exec /app/api
|
exec /app/api
|
||||||
|
|||||||
Reference in New Issue
Block a user