feat(deployment): replace monster scripts with modular helper scripts (#87)
- Add install.sh orchestrator with upgrade support - Add 6 helper scripts (<100 lines each) replacing 700-800 line monsters - Add deployment/linux/furt.service systemd template - Support both fresh install and upgrade modes - Platform-aware detection (OpenBSD/FreeBSD vs Linux) - Skip user/service creation in upgrade mode - Preserve existing configuration during updates - Remove merkwerk dependency from production install script Helper scripts: - scripts/setup-user.sh - Create system user (_furt/furt) - scripts/setup-directories.sh - Create directory structure - scripts/sync-files.sh - Copy source files to installation - scripts/create-service.sh - Create system service from templates - scripts/validate-config.sh - Validate furt.conf syntax - scripts/health-check.sh - Basic health check functionality Closes DAW/furt#87
This commit is contained in:
parent
8ad77860d1
commit
38a1108a46
8 changed files with 353 additions and 0 deletions
18
deployment/linux/furt.service
Normal file
18
deployment/linux/furt.service
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[Unit]
|
||||
Description=furt Multi-Tenant API Gateway
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=furt
|
||||
Group=furt
|
||||
ExecStart=/usr/local/share/furt/scripts/start.sh start
|
||||
WorkingDirectory=/usr/local/share/furt
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
122
install.sh
Executable file
122
install.sh
Executable file
|
|
@ -0,0 +1,122 @@
|
|||
#!/bin/sh
|
||||
# install.sh - furt Installation and Update Orchestrator
|
||||
|
||||
set -e
|
||||
|
||||
# Parse command line arguments
|
||||
UPGRADE_MODE=false
|
||||
SKIP_USER=false
|
||||
SKIP_SERVICE=false
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--upgrade) UPGRADE_MODE=true; shift ;;
|
||||
--skip-user) SKIP_USER=true; shift ;;
|
||||
--skip-service) SKIP_SERVICE=true; shift ;;
|
||||
--help)
|
||||
echo "Usage: $0 [--upgrade] [--skip-user] [--skip-service]"
|
||||
echo " --upgrade Update existing installation (skip user/service creation)"
|
||||
echo " --skip-user Skip user creation step"
|
||||
echo " --skip-service Skip service creation step"
|
||||
exit 0
|
||||
;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate we're in furt source directory
|
||||
if [ ! -f "src/main.lua" ] || [ ! -d "scripts" ]; then
|
||||
echo "Error: Not in furt source directory"
|
||||
echo "Expected files: src/main.lua, scripts/ directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== furt Installation ==="
|
||||
if [ "$UPGRADE_MODE" = "true" ]; then
|
||||
echo "Mode: Upgrade (preserving config and service)"
|
||||
else
|
||||
echo "Mode: Fresh installation"
|
||||
fi
|
||||
|
||||
# Step 1: Create system user (skip in upgrade mode)
|
||||
if [ "$UPGRADE_MODE" = "false" ] && [ "$SKIP_USER" = "false" ]; then
|
||||
echo "\n[1/6] Creating system user..."
|
||||
./scripts/setup-user.sh
|
||||
else
|
||||
echo "\n[1/6] Skipping user creation (upgrade mode)"
|
||||
fi
|
||||
|
||||
# Step 2: Setup directories
|
||||
echo "\n[2/6] Setting up directories..."
|
||||
./scripts/setup-directories.sh
|
||||
|
||||
# Step 3: Sync source files (always needed for updates)
|
||||
echo "\n[3/6] Syncing source files..."
|
||||
./scripts/sync-files.sh
|
||||
|
||||
# Step 4: Create service (skip in upgrade mode unless requested)
|
||||
if [ "$UPGRADE_MODE" = "false" ] && [ "$SKIP_SERVICE" = "false" ]; then
|
||||
echo "\n[4/6] Creating system service..."
|
||||
./scripts/create-service.sh
|
||||
else
|
||||
echo "\n[4/6] Skipping service creation (upgrade mode)"
|
||||
fi
|
||||
|
||||
# Step 5: Validate configuration
|
||||
echo "\n[5/6] Validating configuration..."
|
||||
if ./scripts/validate-config.sh; then
|
||||
echo "Configuration validation successful"
|
||||
else
|
||||
echo "Warning: Configuration validation failed - manual setup may be needed"
|
||||
fi
|
||||
|
||||
# Step 6: Health check
|
||||
echo "\n[6/6] Performing health check..."
|
||||
if ./scripts/health-check.sh >/dev/null 2>&1; then
|
||||
echo "Health check passed - furt is running"
|
||||
else
|
||||
echo "Health check failed - service may need to be started manually"
|
||||
fi
|
||||
|
||||
# Installation summary
|
||||
echo "\n=== Installation Summary ==="
|
||||
if [ "$UPGRADE_MODE" = "true" ]; then
|
||||
echo "furt upgrade completed successfully"
|
||||
echo ""
|
||||
echo "Source code updated to:"
|
||||
if [ -f "/usr/local/share/furt/VERSION" ]; then
|
||||
echo " Version: $(cat /usr/local/share/furt/VERSION)"
|
||||
fi
|
||||
if [ -f "/usr/local/share/furt/.version_history" ]; then
|
||||
echo " Version history available (for furt internal tracking)"
|
||||
fi
|
||||
echo ""
|
||||
echo "Service restart required:"
|
||||
if [ "$(uname)" = "OpenBSD" ]; then
|
||||
echo " doas rcctl restart furt"
|
||||
else
|
||||
echo " sudo systemctl restart furt"
|
||||
fi
|
||||
else
|
||||
echo "furt installation completed successfully"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Edit configuration file:"
|
||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
||||
echo " /usr/local/etc/furt/furt.conf"
|
||||
else
|
||||
echo " /etc/furt/furt.conf"
|
||||
fi
|
||||
echo "2. Start the service:"
|
||||
if [ "$(uname)" = "OpenBSD" ]; then
|
||||
echo " doas rcctl start furt"
|
||||
else
|
||||
echo " sudo systemctl start furt"
|
||||
fi
|
||||
echo "3. Test the API:"
|
||||
echo " curl http://127.0.0.1:7811/health"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Installation log available in system logs"
|
||||
|
||||
41
scripts/create-service.sh
Executable file
41
scripts/create-service.sh
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh
|
||||
# scripts/create-service.sh - Create system service for furt using repository templates
|
||||
|
||||
set -e
|
||||
|
||||
# Check if we're in furt source directory
|
||||
if [ ! -d "deployment" ]; then
|
||||
echo "Error: deployment/ directory not found - not in furt source directory?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(uname)" = "OpenBSD" ]; then
|
||||
# Use OpenBSD rc.d template from repository
|
||||
if [ ! -f "deployment/openbsd/rc.d-furt" ]; then
|
||||
echo "Error: deployment/openbsd/rc.d-furt template not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp deployment/openbsd/rc.d-furt /etc/rc.d/furt
|
||||
chmod +x /etc/rc.d/furt
|
||||
echo "furt_flags=" >> /etc/rc.conf.local
|
||||
rcctl enable furt
|
||||
echo "OpenBSD service created and enabled using repository template"
|
||||
|
||||
elif [ "$(uname)" = "Linux" ]; then
|
||||
# Use systemd template from repository
|
||||
if [ ! -f "deployment/linux/furt.service" ]; then
|
||||
echo "Error: deployment/linux/furt.service template not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp deployment/linux/furt.service /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
systemctl enable furt
|
||||
echo "Linux systemd service created and enabled using repository template"
|
||||
|
||||
else
|
||||
echo "Unsupported operating system for service creation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
40
scripts/health-check.sh
Executable file
40
scripts/health-check.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/sh
|
||||
# scripts/health-check.sh - Basic health check for furt service
|
||||
|
||||
set -e
|
||||
|
||||
# Default values
|
||||
HOST="127.0.0.1"
|
||||
PORT="7811"
|
||||
|
||||
# Parse command line arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--host) HOST="$2"; shift 2 ;;
|
||||
--port) PORT="$2"; shift 2 ;;
|
||||
*) echo "Usage: $0 [--host HOST] [--port PORT]"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Checking furt health at $HOST:$PORT..."
|
||||
|
||||
# Check if port is listening
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
if curl -s "http://$HOST:$PORT/health" > /tmp/health_response; then
|
||||
echo "Health check successful:"
|
||||
cat /tmp/health_response | sed 's/^/ /'
|
||||
rm -f /tmp/health_response
|
||||
else
|
||||
echo "Health check failed - service not responding"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Warning: curl not available, using basic port check"
|
||||
if nc -z "$HOST" "$PORT" 2>/dev/null; then
|
||||
echo "Port $PORT is listening on $HOST"
|
||||
else
|
||||
echo "Port $PORT is not accessible on $HOST"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
29
scripts/setup-directories.sh
Executable file
29
scripts/setup-directories.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh
|
||||
# scripts/setup-directories.sh - Create directory structure for furt
|
||||
|
||||
set -e
|
||||
|
||||
# Detect operating system for config directory
|
||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
||||
CONFIG_DIR="/usr/local/etc/furt"
|
||||
USER="_furt"
|
||||
GROUP="_furt"
|
||||
else
|
||||
CONFIG_DIR="/etc/furt"
|
||||
USER="furt"
|
||||
GROUP="furt"
|
||||
fi
|
||||
|
||||
# Create directories
|
||||
mkdir -p "$CONFIG_DIR"
|
||||
mkdir -p /usr/local/share/furt
|
||||
mkdir -p /var/log/furt
|
||||
|
||||
# Set ownership for log directory (service user needs write access)
|
||||
chown "$USER:$GROUP" /var/log/furt
|
||||
|
||||
echo "Created directories:"
|
||||
echo " Config: $CONFIG_DIR"
|
||||
echo " Share: /usr/local/share/furt"
|
||||
echo " Logs: /var/log/furt (owned by $USER)"
|
||||
|
||||
20
scripts/setup-user.sh
Executable file
20
scripts/setup-user.sh
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
# scripts/setup-user.sh - Create _furt system user and group
|
||||
|
||||
set -e
|
||||
|
||||
# Detect operating system
|
||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
||||
# BSD systems use _furt user convention
|
||||
groupadd _furt 2>/dev/null || true
|
||||
useradd -g _furt -s /bin/false -d /var/empty _furt 2>/dev/null || true
|
||||
echo "Created BSD system user: _furt"
|
||||
else
|
||||
# Linux systems use furt user with --system flag
|
||||
groupadd --system furt 2>/dev/null || true
|
||||
useradd --system -g furt -s /bin/false -d /var/empty furt 2>/dev/null || true
|
||||
echo "Created Linux system user: furt"
|
||||
fi
|
||||
|
||||
echo "User setup completed successfully"
|
||||
|
||||
34
scripts/sync-files.sh
Executable file
34
scripts/sync-files.sh
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/sh
|
||||
# scripts/sync-files.sh - Copy furt source files to installation directory
|
||||
|
||||
set -e
|
||||
|
||||
# Check if we're in a furt source directory
|
||||
if [ ! -f "src/main.lua" ]; then
|
||||
echo "Error: Not in furt source directory (src/main.lua not found)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Target directory
|
||||
TARGET="/usr/local/share/furt"
|
||||
|
||||
echo "Copying furt files to $TARGET..."
|
||||
|
||||
# Copy main directories
|
||||
cp -r src/ "$TARGET/"
|
||||
cp -r config/ "$TARGET/"
|
||||
cp -r scripts/ "$TARGET/"
|
||||
cp -r integrations/ "$TARGET/"
|
||||
|
||||
# Copy version files for merkwerk integration
|
||||
[ -f "VERSION" ] && cp VERSION "$TARGET/"
|
||||
[ -f ".version_history" ] && cp .version_history "$TARGET/"
|
||||
|
||||
# Set proper permissions
|
||||
chown -R root:wheel "$TARGET" 2>/dev/null || chown -R root:root "$TARGET"
|
||||
chmod -R 644 "$TARGET"
|
||||
find "$TARGET" -type d -exec chmod 755 {} \;
|
||||
chmod +x "$TARGET/scripts/start.sh"
|
||||
|
||||
echo "Files synced successfully to $TARGET"
|
||||
|
||||
49
scripts/validate-config.sh
Executable file
49
scripts/validate-config.sh
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
# scripts/validate-config.sh - Validate furt configuration
|
||||
|
||||
set -e
|
||||
|
||||
# Detect config file location
|
||||
if [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "FreeBSD" ]; then
|
||||
CONFIG_FILE="/usr/local/etc/furt/furt.conf"
|
||||
else
|
||||
CONFIG_FILE="/etc/furt/furt.conf"
|
||||
fi
|
||||
|
||||
echo "Validating configuration: $CONFIG_FILE"
|
||||
|
||||
# Check if config file exists
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Error: Configuration file not found: $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Basic INI syntax validation
|
||||
if ! grep -q '^\[server\]' "$CONFIG_FILE"; then
|
||||
echo "Error: [server] section missing in config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '^port\s*=' "$CONFIG_FILE"; then
|
||||
echo "Error: server port not configured"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '^host\s*=' "$CONFIG_FILE"; then
|
||||
echo "Error: server host not configured"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for at least one API key
|
||||
if ! grep -q '^\[api_key' "$CONFIG_FILE"; then
|
||||
echo "Warning: No API keys configured"
|
||||
fi
|
||||
|
||||
# Check permissions (should not be world-readable due to secrets)
|
||||
PERMS=$(stat -c '%a' "$CONFIG_FILE" 2>/dev/null || stat -f '%Lp' "$CONFIG_FILE")
|
||||
if [ "$PERMS" -gt 640 ]; then
|
||||
echo "Warning: Config file permissions too open ($PERMS), should be 640"
|
||||
fi
|
||||
|
||||
echo "Configuration validation completed"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue