Initial commit
This commit is contained in:
298
skills/flox-services/SKILL.md
Normal file
298
skills/flox-services/SKILL.md
Normal file
@@ -0,0 +1,298 @@
|
||||
---
|
||||
name: flox-services
|
||||
description: Running services and background processes in Flox environments. Use for service configuration, network services, logging, database setup, and service debugging.
|
||||
---
|
||||
|
||||
# Flox Services Guide
|
||||
|
||||
## Running Services in Flox Environments
|
||||
|
||||
- Start with `flox activate --start-services` or `flox activate -s`
|
||||
- Define `is-daemon`, `shutdown.command` for background processes
|
||||
- Keep services running using `tail -f /dev/null`
|
||||
- Use `flox services status/logs/restart` to manage (must be in activated env)
|
||||
- Service commands don't inherit hook activations; explicitly source/activate what you need
|
||||
|
||||
## Core Commands
|
||||
|
||||
```bash
|
||||
flox activate -s # Start services
|
||||
flox services status # Check service status
|
||||
flox services logs <service> # View service logs
|
||||
flox services restart <service> # Restart a service
|
||||
flox services stop <service> # Stop a service
|
||||
```
|
||||
|
||||
## Network Services Pattern
|
||||
|
||||
Always make host/port configurable via vars:
|
||||
|
||||
```toml
|
||||
[services.webapp]
|
||||
command = '''exec app --host "$APP_HOST" --port "$APP_PORT"'''
|
||||
|
||||
[vars]
|
||||
APP_HOST = "0.0.0.0" # Network-accessible
|
||||
APP_PORT = "8080"
|
||||
```
|
||||
|
||||
## Service Logging Pattern
|
||||
|
||||
Always pipe to `$FLOX_ENV_CACHE/logs/` for debugging:
|
||||
|
||||
```toml
|
||||
[services.myapp]
|
||||
command = '''
|
||||
mkdir -p "$FLOX_ENV_CACHE/logs"
|
||||
exec app 2>&1 | tee -a "$FLOX_ENV_CACHE/logs/app.log"
|
||||
'''
|
||||
```
|
||||
|
||||
## Python venv Pattern for Services
|
||||
|
||||
Services must activate venv independently:
|
||||
|
||||
```toml
|
||||
[services.myapp]
|
||||
command = '''
|
||||
[ -f "$FLOX_ENV_CACHE/venv/bin/activate" ] && \
|
||||
source "$FLOX_ENV_CACHE/venv/bin/activate"
|
||||
exec python-app "$@"
|
||||
'''
|
||||
```
|
||||
|
||||
Or use venv Python directly:
|
||||
|
||||
```toml
|
||||
[services.myapp]
|
||||
command = '''exec "$FLOX_ENV_CACHE/venv/bin/python" app.py'''
|
||||
```
|
||||
|
||||
## Using Packaged Services
|
||||
|
||||
Override package's service by redefining with same name.
|
||||
|
||||
## Database Service Examples
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```toml
|
||||
[services.postgres]
|
||||
command = '''
|
||||
mkdir -p "$FLOX_ENV_CACHE/postgres"
|
||||
if [ ! -d "$FLOX_ENV_CACHE/postgres/data" ]; then
|
||||
initdb -D "$FLOX_ENV_CACHE/postgres/data"
|
||||
fi
|
||||
exec postgres -D "$FLOX_ENV_CACHE/postgres/data" \
|
||||
-k "$FLOX_ENV_CACHE/postgres" \
|
||||
-h "$POSTGRES_HOST" \
|
||||
-p "$POSTGRES_PORT"
|
||||
'''
|
||||
is-daemon = true
|
||||
|
||||
[vars]
|
||||
POSTGRES_HOST = "localhost"
|
||||
POSTGRES_PORT = "5432"
|
||||
POSTGRES_USER = "myuser"
|
||||
POSTGRES_DB = "mydb"
|
||||
```
|
||||
|
||||
### Redis
|
||||
|
||||
```toml
|
||||
[services.redis]
|
||||
command = '''
|
||||
mkdir -p "$FLOX_ENV_CACHE/redis"
|
||||
exec redis-server \
|
||||
--bind "$REDIS_HOST" \
|
||||
--port "$REDIS_PORT" \
|
||||
--dir "$FLOX_ENV_CACHE/redis"
|
||||
'''
|
||||
is-daemon = true
|
||||
|
||||
[vars]
|
||||
REDIS_HOST = "127.0.0.1"
|
||||
REDIS_PORT = "6379"
|
||||
```
|
||||
|
||||
### MongoDB
|
||||
|
||||
```toml
|
||||
[services.mongodb]
|
||||
command = '''
|
||||
mkdir -p "$FLOX_ENV_CACHE/mongodb"
|
||||
exec mongod \
|
||||
--dbpath "$FLOX_ENV_CACHE/mongodb" \
|
||||
--bind_ip "$MONGODB_HOST" \
|
||||
--port "$MONGODB_PORT"
|
||||
'''
|
||||
is-daemon = true
|
||||
|
||||
[vars]
|
||||
MONGODB_HOST = "127.0.0.1"
|
||||
MONGODB_PORT = "27017"
|
||||
```
|
||||
|
||||
## Web Server Examples
|
||||
|
||||
### Node.js Development Server
|
||||
|
||||
```toml
|
||||
[services.dev-server]
|
||||
command = '''
|
||||
exec npm run dev -- --host "$DEV_HOST" --port "$DEV_PORT"
|
||||
'''
|
||||
|
||||
[vars]
|
||||
DEV_HOST = "0.0.0.0"
|
||||
DEV_PORT = "3000"
|
||||
```
|
||||
|
||||
### Python Flask/FastAPI
|
||||
|
||||
```toml
|
||||
[services.api]
|
||||
command = '''
|
||||
source "$FLOX_ENV_CACHE/venv/bin/activate"
|
||||
exec python -m uvicorn main:app \
|
||||
--host "$API_HOST" \
|
||||
--port "$API_PORT" \
|
||||
--reload
|
||||
'''
|
||||
|
||||
[vars]
|
||||
API_HOST = "0.0.0.0"
|
||||
API_PORT = "8000"
|
||||
```
|
||||
|
||||
### Simple HTTP Server
|
||||
|
||||
```toml
|
||||
[services.web]
|
||||
command = '''exec python -m http.server "$WEB_PORT"'''
|
||||
|
||||
[vars]
|
||||
WEB_PORT = "8000"
|
||||
```
|
||||
|
||||
## Environment Variable Convention
|
||||
|
||||
Use variables like `POSTGRES_HOST`, `POSTGRES_PORT` to define where services run.
|
||||
|
||||
These store connection details *separately*:
|
||||
- `*_HOST` is the hostname or IP address (e.g., `localhost`, `db.example.com`)
|
||||
- `*_PORT` is the network port number (e.g., `5432`, `6379`)
|
||||
|
||||
This pattern ensures users can override them at runtime:
|
||||
```bash
|
||||
POSTGRES_HOST=db.internal POSTGRES_PORT=6543 flox activate -s
|
||||
```
|
||||
|
||||
Use consistent naming across services so the meaning is clear to any system or person reading the variables.
|
||||
|
||||
## Service with Shutdown Command
|
||||
|
||||
```toml
|
||||
[services.myapp]
|
||||
command = '''exec myapp start'''
|
||||
is-daemon = true
|
||||
|
||||
[services.myapp.shutdown]
|
||||
command = '''myapp stop'''
|
||||
```
|
||||
|
||||
## Dependent Services
|
||||
|
||||
Services can wait for other services to be ready:
|
||||
|
||||
```toml
|
||||
[services.db]
|
||||
command = '''exec postgres -D "$FLOX_ENV_CACHE/postgres"'''
|
||||
is-daemon = true
|
||||
|
||||
[services.api]
|
||||
command = '''
|
||||
# Wait for database
|
||||
until pg_isready -h localhost -p 5432; do
|
||||
sleep 1
|
||||
done
|
||||
exec python -m uvicorn main:app
|
||||
'''
|
||||
|
||||
[vars]
|
||||
POSTGRES_HOST = "localhost"
|
||||
POSTGRES_PORT = "5432"
|
||||
```
|
||||
|
||||
## Service Health Checks
|
||||
|
||||
```toml
|
||||
[services.api]
|
||||
command = '''
|
||||
# Health check function
|
||||
health_check() {
|
||||
curl -sf http://localhost:8000/health > /dev/null
|
||||
}
|
||||
|
||||
exec python -m uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
'''
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Log service output to `$FLOX_ENV_CACHE/logs/`
|
||||
- Test activation with `flox activate -- <command>` before adding to services
|
||||
- When debugging services, run the exact command from manifest manually first
|
||||
- Always make host/port configurable via vars for network services
|
||||
- Use `exec` to replace the shell process with the service command
|
||||
- Services must activate venv inside service command, not rely on hook activation
|
||||
- Use `is-daemon = true` for background processes that should detach
|
||||
|
||||
## Debugging Service Issues
|
||||
|
||||
### Check Service Status
|
||||
```bash
|
||||
flox services status
|
||||
```
|
||||
|
||||
### View Service Logs
|
||||
```bash
|
||||
flox services logs myservice
|
||||
```
|
||||
|
||||
### Run Service Command Manually
|
||||
```bash
|
||||
flox activate
|
||||
# Copy the exact command from manifest and run it
|
||||
```
|
||||
|
||||
### Check if Service is Listening
|
||||
```bash
|
||||
# Check if port is open
|
||||
lsof -i :8000
|
||||
netstat -an | grep 8000
|
||||
|
||||
# Test connection
|
||||
curl http://localhost:8000
|
||||
nc -zv localhost 8000
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Services Don't Preserve State
|
||||
Services see fresh environment (no preserved state between restarts). Store persistent data in `$FLOX_ENV_CACHE`.
|
||||
|
||||
### Service Commands Don't Inherit Hook Activations
|
||||
Explicitly source/activate what you need inside the service command.
|
||||
|
||||
### Forgetting to Create Directories
|
||||
Always `mkdir -p` for data directories in service commands.
|
||||
|
||||
### Port Conflicts
|
||||
Use configurable ports via variables to avoid conflicts with other services.
|
||||
|
||||
## Related Skills
|
||||
|
||||
- **flox-environments** - Environment basics and package installation
|
||||
- **flox-sharing** - Composing environments with shared services
|
||||
- **flox-containers** - Running services in containers
|
||||
Reference in New Issue
Block a user