summaryrefslogtreecommitdiff
path: root/docs/deployment.md
blob: 5845948f3110e53838d595606414801de8f1b108 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# Deployment Guide

Deploy Task Dashboard to a VPS using Apache2 as reverse proxy and Systemd for process management.

## Prerequisites

- Linux VPS (Ubuntu/Debian recommended)
- Apache2 with `mod_proxy`, `mod_proxy_http`, `mod_ssl`, `mod_headers`, `mod_rewrite`
- Go 1.21+ (for building)
- SSL certificate (Let's Encrypt recommended)

## Directory Structure

```
/site/{fqdn}/
├── app                 # Compiled binary
├── data/
│   └── dashboard.db    # SQLite database
├── public/             # Static assets (served by Apache)
│   ├── css/
│   │   └── output.css
│   └── js/
│       ├── htmx.min.js
│       └── app.js
├── templates/          # HTML templates
│   ├── index.html
│   ├── login.html
│   └── partials/
└── .env                # Environment configuration
```

## Build

On your development machine or CI:

```bash
# Build for Linux
GOOS=linux GOARCH=amd64 go build -o app cmd/dashboard/main.go
```

## Setup

### 1. Create Directory Structure

```bash
export FQDN="your-domain.com"
mkdir -p /site/${FQDN}/{data,public/css,public/js,templates/partials}
```

### 2. Deploy Files

```bash
# Copy binary
cp app /site/${FQDN}/

# Copy static assets
cp -r web/static/* /site/${FQDN}/public/

# Copy templates (including partials)
cp -r web/templates/* /site/${FQDN}/templates/
```

### 3. Set Permissions

**Important:** The app runs as `www-data`. All directories need 755, all files need 644.

```bash
# Set ownership
chown -R www-data:www-data /site/${FQDN}

# Set directory permissions (755 = rwxr-xr-x)
find /site/${FQDN} -type d -exec chmod 755 {} \;

# Set file permissions (644 = rw-r--r--)
find /site/${FQDN} -type f -exec chmod 644 {} \;

# Make binary executable
chmod +x /site/${FQDN}/app
```

### 4. Configure Environment

Create `/site/${FQDN}/.env`:

```bash
# Required API Keys
TODOIST_API_KEY=your_todoist_api_key
TRELLO_API_KEY=your_trello_api_key
TRELLO_TOKEN=your_trello_token

# Optional
PLANTOEAT_API_KEY=your_plantoeat_api_key

# Paths (use absolute paths)
DATABASE_PATH=/site/your-domain.com/data/dashboard.db
TEMPLATE_DIR=/site/your-domain.com/templates
STATIC_DIR=/site/your-domain.com/public

# Server
PORT=8080
DEBUG=false
CACHE_TTL_MINUTES=5

# Default user credentials (change after first login!)
DEFAULT_USER=admin
DEFAULT_PASS=your_secure_password
```

Secure the file:

```bash
chmod 600 /site/${FQDN}/.env
chown www-data:www-data /site/${FQDN}/.env
```

### 5. Install Systemd Service

Copy the service file:

```bash
cp deployment/task-dashboard.service /etc/systemd/system/task-dashboard@.service
```

The default service uses `EnvironmentFile`, but godotenv expects to load `.env` from the working directory. Create an override to source it properly:

```bash
systemctl edit task-dashboard@${FQDN}
```

Add:

```ini
[Service]
ExecStart=
ExecStart=/bin/bash -c 'cd /site/%i && source .env && ./app'
```

Enable and start:

```bash
systemctl daemon-reload
systemctl enable task-dashboard@${FQDN}
systemctl start task-dashboard@${FQDN}

# Check status
systemctl status task-dashboard@${FQDN}
```

### 6. Configure Apache

Enable required modules:

```bash
a2enmod proxy proxy_http ssl headers rewrite
```

Copy and customize Apache config:

```bash
cp deployment/apache.conf /etc/apache2/sites-available/${FQDN}.conf

# Replace ${FQDN} placeholders with your actual domain
sed -i "s/\${FQDN}/${FQDN}/g" /etc/apache2/sites-available/${FQDN}.conf

# Enable site
a2ensite ${FQDN}

# Test and reload
apache2ctl configtest
systemctl reload apache2
```

### 7. SSL Certificate (Let's Encrypt)

```bash
apt install certbot python3-certbot-apache
certbot --apache -d ${FQDN}
```

## Verification

1. Check service is running: `systemctl status task-dashboard@${FQDN}`
2. Check logs: `journalctl -u task-dashboard@${FQDN} -f`
3. Visit `https://${FQDN}` and login with configured credentials
4. Change the default password after first login

## Updating

```bash
# Stop service
systemctl stop task-dashboard@${FQDN}

# Deploy new binary
cp app /site/${FQDN}/

# Update static assets if changed
cp -r web/static/* /site/${FQDN}/public/

# Update templates if changed
cp -r web/templates/* /site/${FQDN}/templates/

# Fix permissions
chown -R www-data:www-data /site/${FQDN}
find /site/${FQDN} -type d -exec chmod 755 {} \;
find /site/${FQDN} -type f -exec chmod 644 {} \;
chmod +x /site/${FQDN}/app
chmod 600 /site/${FQDN}/.env

# Start service
systemctl start task-dashboard@${FQDN}
```

## Troubleshooting

### Service won't start

Check logs:
```bash
journalctl -u task-dashboard@${FQDN} -e
```

Common issues:
- **"TODOIST_API_KEY is required"**: The .env file isn't being loaded. Use the systemctl override to source it (see step 5).
- **"readonly database"**: The `data/` directory isn't writable by www-data. Run `chown www-data:www-data /site/${FQDN}/data`.
- **Template panic/nil pointer**: Template files have wrong permissions. Run `chmod 644` on all `.html` files.

### 502 Bad Gateway

- Check if Go app is running: `systemctl status task-dashboard@${FQDN}`
- Verify PORT in .env matches Apache ProxyPass (default: 8080)

### AH01144: No protocol handler was valid

Apache proxy modules aren't loaded:
```bash
a2enmod proxy proxy_http
systemctl restart apache2
```

### 403 Forbidden on static files

Permission issue. Fix:
```bash
chmod -R 755 /site/${FQDN}/public
find /site/${FQDN}/public -type f -exec chmod 644 {} \;
chown -R www-data:www-data /site/${FQDN}/public
```

### 404 on static files

Static files not copied. Ensure the structure exists:
```bash
ls -la /site/${FQDN}/public/css/output.css
ls -la /site/${FQDN}/public/js/htmx.min.js
ls -la /site/${FQDN}/public/js/app.js
```

If missing, copy from `web/static/`.