homelab infrastructure services
1# Creating a New Machine
2
3This guide covers setting up a new machine in the tinsnip infrastructure, including prerequisites, NFS setup, machine configuration, and testing.
4
5## Decisions to Make First
6
7Before starting, you need to decide on these key inputs:
8
9### 1. Service Name
10Give the thing you are making a name - this might be the product name (lldap or caddy) or a name which wraps a product of your own like gazette or daffodyl.
11- Currently configured: `tinsnip`, `gazette`
12- You can add more in the future
13
14### 2. Environment
15Decide if this is for production use or testing. This affects which UID and ports get assigned.
16- `prod` - Production environment (UID: xxx00)
17- `test` - Test environment (UID: xxx10)
18
19### 3. NAS Server
20Provide the hostname or IP address of your NAS where data will be stored.
21- Hostname example: `DS412plus`, `nas.local`
22- IP example: `192.168.1.100`
23
24### 4. Sheet (Optional)
25If you're running services for multiple organizations or want to separate your services from the default, set a custom sheet.
26- Default: `dynamicalsystem`
27- Custom: Your organization name (e.g., `mycompany`)
28
29## Prerequisites
30
31### Machine Requirements
32- **OS**: Ubuntu 20.04 or later (tested on 20.04 and 22.04)
33- **User**: Account with sudo privileges
34- **Network**: Access to NAS and internet for Docker installation
35- **Resources**: At least 2GB RAM, 10GB disk space
36
37### NAS Requirements
38- **Synology NAS** with DSM 6.x or later
39- **SSH access** to NAS with administrative privileges
40- **Available storage** for service data
41
42### Verify Prerequisites
43
44```bash
45# Check Ubuntu version
46lsb_release -a
47
48# Check sudo access
49sudo -v && echo "✓ sudo access confirmed" || echo "✗ Need sudo access"
50
51# Test NAS connectivity
52ping -c 1 your-nas-hostname
53```
54
55## Overview
56
57Creating a new machine involves:
581. **Sheet Configuration**: Set the organizational sheet (defaults to `dynamicalsystem`)
592. **NAS Setup**: Create NFS exports with proper UID mapping
603. **Machine Setup**: Install and configure the machine environment
614. **Service Deployment**: Deploy services with proper isolation
625. **Testing**: Validate the complete setup
63
64
65## Step 1: Tinsnip Sheet Configuration
66
67The system supports configurable sheets for multi-tenant deployments. The sheet affects NFS paths and XDG directory organization.
68
69### Setting the Sheet
70
71**Option 1: Environment Variable**
72```bash
73export TIN_SHEET=mycompany
74./machine/setup.sh tinsnip test DS412plus
75```
76
77**Option 2: System-wide Configuration**
78```bash
79echo "mycompany" | sudo tee /etc/tinsnip-sheet
80./machine/setup.sh tinsnip test DS412plus
81```
82
83**Default**: If no sheet is configured, `dynamicalsystem` is used.
84
85For detailed sheet configuration options, see [SHEET_CONFIGURATION.md](SHEET_CONFIGURATION.md).
86
87## Step 2: NAS Setup (Critical)
88
89### Create Directory Structure
90
91On your Synology NAS, create the directory structure for your sheet:
92
93```bash
94# For topsheet (default sheet, most users deploy here)
95/volume1/topsheet/
96├── station/
97│ ├── prod/ (will be owned by UID 50000)
98│ └── test/ (will be owned by UID 50010)
99└── gazette/
100 ├── prod/ (will be owned by UID 50100)
101 └── test/ (will be owned by UID 50110)
102
103# For custom sheet (infrastructure)
104/volume1/tinsnip/infrastructure/
105├── station/
106│ ├── prod/ (will be owned by UID 10000)
107│ └── test/ (will be owned by UID 10010)
108└── gazette/
109 ├── prod/ (will be owned by UID 11000)
110 └── test/ (will be owned by UID 11110)
111```
112
113**Create directories and set ownership:**
114```bash
115# SSH into NAS
116ssh admin@synology-ip
117
118# Create directory structure (replace {sheet} with your sheet)
119sudo mkdir -p /volume1/{sheet}/{tinsnip,gazette}/{prod,test}
120
121# Set ownership to match service UIDs
122sudo chown 11000:11000 /volume1/{sheet}/tinsnip/prod
123sudo chown 11010:11010 /volume1/{sheet}/tinsnip/test
124sudo chown 11100:11100 /volume1/{sheet}/gazette/prod
125sudo chown 11110:11110 /volume1/{sheet}/gazette/test
126
127# Example for custom sheet:
128sudo mkdir -p /volume1/mycompany/{tinsnip,gazette}/{prod,test}
129sudo chown 11000:11000 /volume1/mycompany/tinsnip/prod
130sudo chown 11010:11010 /volume1/mycompany/tinsnip/test
131sudo chown 11100:11100 /volume1/mycompany/gazette/prod
132sudo chown 11110:11110 /volume1/mycompany/gazette/test
133```
134
135**Important**: The `chown` commands ensure the directories are owned by the correct UIDs before NFS export. This is critical for proper permissions.
136
137### Configure NFS Exports
138
139**IMPORTANT**: The Synology DSM GUI cannot map to specific UIDs (11000+), so you must configure exports via SSH.
140
141#### Option 1: Generate Export Rules Automatically (Recommended)
142
143Use the NFS export generator to create the exact rules you need:
144
145```bash
146# Interactive mode - prompts for all inputs
147cd machine
148./generate_nfs_exports.sh
149
150# Direct mode - provide all parameters
151./generate_nfs_exports.sh tinsnip test dynamicalsystem ubuntu-machine.local
152
153# Example output shows:
154# - Directory creation commands
155# - Ownership commands
156# - Export rules to add to /etc/exports
157# - Test commands
158```
159
160#### Option 2: Manual Configuration
161
1621. **SSH into Synology NAS:**
163```bash
164ssh admin@synology-ip
165```
166
1672. **Edit /etc/exports file:**
168```bash
169sudo vi /etc/exports
170```
171
1723. **Add export rules (CRITICAL: Use TAB characters between path and options):**
173
174Use the output from the generator above, or manually create rules like:
175```
176/volume1/{sheet}/{service}/{env} {client-host}(rw,async,no_subtree_check,all_squash,anonuid={uid},anongid={uid})
177```
178
1794. **Reload NFS exports:**
180```bash
181sudo exportfs -ra
182```
183
1845. **Verify exports are active:**
185```bash
186sudo exportfs -v
187```
188
189## Step 3: Machine Setup
190
191### Install Machine Setup Tools
192
193The machine setup tools provide automated scripts for creating service users, mounting NFS, and installing rootless Docker.
194
195```bash
196# One-line installation - downloads scripts to ~/.local/opt/dynamicalsystem.machine
197curl -fsSL "https://tangled.sh/dynamicalsystem.com/machine/raw/main/install.sh?$(date +%s)" | bash
198
199# Navigate to installation directory
200cd ~/.local/opt/dynamicalsystem.machine
201```
202
203**What this installs:**
204- `setup.sh` - Main orchestration script for service environment creation
205- `scripts/` - Helper scripts for NFS mounting, Docker installation, etc.
206- `machine/` - Service-specific setup scripts with sheet support
207
208### Run Validations (Optional)
209
210Before making any system changes, you can optionally validate the setup logic:
211
212```bash
213cd machine
214./validate.sh
215```
216
217Running validations is recommended but not required.
218
219### Create Service Environment
220
221Run the setup script from the machine directory:
222
223**Interactive setup (recommended for first time):**
224```bash
225cd machine
226./setup.sh
227# Will prompt for:
228# - Service name (tinsnip or gazette)
229# - Environment (test or prod)
230# - NAS server hostname/IP
231```
232
233**Direct setup (if you know the parameters):**
234```bash
235cd machine
236./setup.sh tinsnip test DS412plus # Creates tinsnip-test environment
237./setup.sh gazette prod 192.168.1.100 # Creates gazette-prod environment
238
239# With custom sheet:
240TIN_SHEET=mycompany ./setup.sh tinsnip prod nas.mycompany.local
241```
242
243### What Gets Created
244
245The setup creates:
246
2471. **Service User**: `tinsnip-test` (UID 11010) with dedicated home directory
2482. **NFS Mount**: `/mnt/tinsnip-test` → `DS412plus:/volume1/{sheet}/tinsnip/test`
2493. **XDG Integration**: Symlinks in `~/.local/{state,share,config}/{sheet}/@tinsnip`
2504. **Rootless Docker**: Installed for service user with privileged port support
2515. **Directory Structure**:
252 ```
253 /mnt/tinsnip-test/
254 ├── state/ # Service state (logs, history)
255 ├── data/ # Service data files
256 └── config/ # Service configuration
257 ```
258
259## Step 4: Service Deployment
260
261### Switch to Service User
262
263```bash
264# Switch to service user context
265sudo -u tinsnip-test -i
266```
267
268### Deploy Service
269
270Create service configuration in the mounted NFS directory:
271
272```bash
273cd /mnt/tinsnip-test
274mkdir -p service/lldap
275
276# Create docker-compose.yml for the service
277cat > service/lldap/docker-compose.yml << 'EOF'
278services:
279 lldap:
280 image: lldap/lldap:stable
281 ports:
282 - "11010:3890" # LDAP port (UID-based)
283 - "11011:17170" # Web UI port (UID-based)
284 volumes:
285 - ../data:/data
286 user: "11010:11010" # Run as service UID
287 environment:
288 - LLDAP_JWT_SECRET_FILE=/data/jwt_secret
289 - LLDAP_KEY_SEED_FILE=/data/key_seed
290 - LLDAP_BASE_DN=dc=home,dc=local
291EOF
292
293# Deploy the service
294cd service/lldap
295docker compose up -d
296```
297
298## Step 5: Testing
299
300### Basic Validation
301
302```bash
303# Check service user
304id tinsnip-test # Should show UID 11010
305
306# Verify NFS mount
307mount | grep /mnt/tinsnip-test
308ls -la /mnt/tinsnip-test/ # Should show correct ownership
309
310# Check XDG symlinks
311ls -la ~/.local/state/dynamicalsystem/@tinsnip # Should point to /mnt/tinsnip-test/state
312
313# Test Docker
314sudo -u tinsnip-test docker --version
315sudo -u tinsnip-test docker run hello-world
316```
317
318### Service Testing
319
320```bash
321# Check service status
322sudo -u tinsnip-test -i
323cd /mnt/tinsnip-test/service/lldap
324docker compose ps
325
326# Test service connectivity
327curl -I http://localhost:11011 # Web UI
328ldapsearch -H ldap://localhost:11010 -b "dc=home,dc=local" # LDAP
329```
330
331### VM Testing Plan
332
333For comprehensive testing, follow the [VM Test Plan](machine/VM_TEST_PLAN.md):
334
3351. **Function Tests**: Validate UID calculation and port allocation
3362. **Partial Tests**: Test user creation and NFS connectivity
3373. **Full Setup**: Complete service environment creation
3384. **Service Deployment**: Deploy and test actual services
339
340## Troubleshooting
341
342### NFS Mount Issues
343
344```bash
345# Test NFS connectivity manually (adjust path for your sheet)
346sudo mount -t nfs DS412plus:/volume1/{sheet}/tinsnip/test /tmp/test-mount
347ls -la /tmp/test-mount # Should show UID 11010 ownership
348sudo umount /tmp/test-mount
349
350# Check NFS exports on server
351ssh admin@DS412plus sudo exportfs -v
352```
353
354### Permission Issues
355
356```bash
357# Verify UID mapping
358sudo -u tinsnip-test touch /mnt/tinsnip-test/test-file
359ls -la /mnt/tinsnip-test/test-file # Should show UID 11010
360
361# Check from NAS side (adjust path for your sheet)
362ssh admin@DS412plus ls -la /volume1/{sheet}/tinsnip/test/
363```
364
365### Docker Issues
366
367```bash
368# Check rootless Docker status
369sudo -u tinsnip-test systemctl --user status docker
370
371# Test privileged ports
372sudo -u tinsnip-test docker run -p 80:80 nginx:alpine
373```
374
375## Rollback Plan
376
377If setup fails or needs to be undone:
378
379```bash
380# Stop containers
381sudo -u tinsnip-test -i bash -c 'docker stop $(docker ps -q)' || true
382
383# Remove service user
384sudo pkill -u tinsnip-test || true
385sudo userdel -r tinsnip-test
386
387# Unmount NFS
388sudo umount /mnt/tinsnip-test || true
389sudo rm -rf /mnt/tinsnip-test
390
391# Clean up XDG symlinks (adjust paths for your sheet)
392rm -rf ~/.local/state/{sheet}/@tinsnip
393rm -rf ~/.local/share/{sheet}/@tinsnip
394rm -rf ~/.config/{sheet}/@tinsnip
395```
396
397## Security Considerations
398
399- Each service runs under dedicated UID for complete isolation
400- NFS `all_squash` ensures consistent file ownership
401- Rootless Docker provides container isolation without root privileges
402- Services cannot access each other's data due to UID separation
403
404## Next Steps
405
406After successful machine creation:
407
4081. **Service Configuration**: Configure service-specific settings
4092. **Integration Testing**: Test with other tinsnip services
4103. **Monitoring Setup**: Add service monitoring and logging
4114. **Backup Validation**: Ensure data backup processes work
412
413For service-specific deployment patterns and UID conventions, see [DEPLOYMENT_STRATEGY.md](DEPLOYMENT_STRATEGY.md).