Add Rocky Podman/Cockpit deployment fixes

This commit is contained in:
Nate Emmert committed 2026-03-11 08:12:06 -04:00
1 parent 5c062fb2cb
commit 7c24f1ecea
7 files changed
+201 -77

No files matched your search

+118 -23
View File
@@ -1,4 +1,59 @@
# Capsule Budget - ZimaOS Deployment Guide # Capsule Budget Deployment Guide
## Rocky Linux + Cockpit + Podman (Recommended)
This is the easiest path for Rocky Linux servers managed with Cockpit.
### 1) Install prerequisites on Rocky Linux
```bash
sudo dnf install -y podman podman-compose cockpit cockpit-podman git
sudo systemctl enable --now cockpit.socket
```
Optional firewall rules:
```bash
sudo firewall-cmd --add-service=cockpit --permanent
sudo firewall-cmd --add-port=7654/tcp --permanent
sudo firewall-cmd --reload
```
### 2) Clone and configure Capsule
```bash
git clone https://github.com/nmemmert/budget.git capsule-budget
cd capsule-budget
cp .env.example .env
```
Generate and set encryption key:
```bash
openssl rand -base64 32
# paste the value into .env as ENCRYPTION_KEY=...
```
### 3) Deploy with Podman Compose
```bash
podman-compose up -d --build
```
If your Podman version provides the compose subcommand, this also works:
```bash
podman compose up -d --build
```
### 4) Manage in Cockpit
1. Open Cockpit at `https://your-server:9090`
2. Go to **Podman Containers**
3. Verify `capsule-budget` is running
4. Use Logs/Start/Stop/Restart directly from Cockpit
Access Capsule at: `http://your-server:7654`
## Installation Methods ## Installation Methods
@@ -39,7 +94,7 @@ curl -fsSL https://raw.githubusercontent.com/nmemmert/budget/master/install.sh |
This will: This will:
- Generate a secure encryption key - Generate a secure encryption key
- Clear any test data - Clear any test data
- Build the Docker image - Build the container image
- Start the container - Start the container
3. **Access Capsule:** 3. **Access Capsule:**
@@ -67,23 +122,23 @@ If you prefer manual setup:
4. **Build and start:** 4. **Build and start:**
```bash ```bash
docker-compose up -d podman-compose up -d
``` ```
## Data Persistence ## Data Persistence
**IMPORTANT: Your data is safely stored outside the Docker container** **IMPORTANT: Your data is safely stored outside the container**
### How It Works ### How It Works
The Docker setup uses a **bind mount** to persist data: The compose setup uses a **bind mount** to persist data:
```yaml ```yaml
volumes: volumes:
- ./data:/app/data # Host directory : Container directory - ./data:/app/data:Z # Host directory : Container directory
``` ```
- **Host Location**: `./data/` (on your ZimaOS filesystem) - **Host Location**: `./data/` (on your host filesystem)
- **Container Location**: `/app/data/` (inside the container) - **Container Location**: `/app/data/` (inside the container)
- **What's Stored**: - **What's Stored**:
- User credentials (hashed) - User credentials (hashed)
@@ -95,13 +150,13 @@ volumes:
✅ Container restarts ✅ Container restarts
✅ Container rebuilds ✅ Container rebuilds
✅ Docker Compose down/up ✅ Podman Compose down/up
✅ System reboots (with restart: unless-stopped) ✅ System reboots (with restart: unless-stopped)
### Data is Lost If ### Data is Lost If
❌ You delete the `./data` directory ❌ You delete the `./data` directory
❌ You run `docker-compose down -v` (removes volumes) ❌ You run `podman-compose down -v` (removes volumes)
### Testing Persistence ### Testing Persistence
@@ -134,16 +189,17 @@ tar -xzf capsule-backup-YYYYMMDD.tar.gz
- Enable automatic snapshots for the Capsule directory - Enable automatic snapshots for the Capsule directory
- Or use ZimaOS built-in backup features - Or use ZimaOS built-in backup features
### Data Location on ZimaOS ### Data Location on Rocky Linux / Podman
Depending on where you deploy: Depending on where you deploy:
- **SMB/File Manager**: Check the upload location - **SMB/File Manager**: Check the upload location
- **SSH Deployment**: Usually `/mnt/your-pool/apps/capsule/data` - **SSH Deployment**: Usually `/mnt/your-pool/apps/capsule/data`
- **Docker Apps**: May be in `/var/lib/docker/volumes/` - **Rootful Podman**: Usually under `/var/lib/containers/storage/`
- **Rootless Podman**: Usually under `~/.local/share/containers/storage/`
To find exact location: To find exact location:
```bash ```bash
docker inspect capsule-budget | grep -A 10 "Mounts" podman inspect capsule-budget | grep -A 10 "Mounts"
``` ```
## ZimaOS Integration ## ZimaOS Integration
@@ -183,20 +239,20 @@ cp -r data data-backup-$(date +%Y%m%d)
```bash ```bash
# View logs # View logs
docker-compose logs -f podman-compose logs -f
# Stop Capsule # Stop Capsule
docker-compose stop podman-compose stop
# Restart Capsule # Restart Capsule
docker-compose restart podman-compose restart
# Stop and remove container # Stop and remove container
docker-compose down podman-compose down
# Rebuild after updates # Rebuild after updates
docker-compose build --no-cache podman-compose build --no-cache
docker-compose up -d podman-compose up -d
``` ```
## Updating Capsule ## Updating Capsule
@@ -206,9 +262,9 @@ docker-compose up -d
git pull git pull
# Rebuild and restart # Rebuild and restart
docker-compose down podman-compose down
docker-compose build podman-compose build
docker-compose up -d podman-compose up -d
``` ```
Your data in `./data/` will persist across updates. Your data in `./data/` will persist across updates.
@@ -225,12 +281,51 @@ Your data in `./data/` will persist across updates.
### Container won't start ### Container won't start
```bash ```bash
# Check logs # Check logs
docker-compose logs podman-compose logs
# Verify .env file exists # Verify .env file exists
ls -la .env ls -la .env
``` ```
### Error: Failed to transpile next.config.ts / Cannot find module 'typescript'
Cause: production containers prune devDependencies, and `next.config.ts` requires TypeScript at runtime.
Fix:
```bash
# Pull latest changes that include next.config.mjs
git pull
# Rebuild image without cache and restart
podman-compose down
podman-compose build --no-cache
podman-compose up -d
```
### Error: EACCES permission denied on /app/data/locks
Cause: bind mount permissions/labels are not writable for the Podman container context.
Fix:
```bash
# Stop container
podman-compose down
# Ensure data dir exists and is writable
mkdir -p data
chmod 0777 data
# Rebuild and restart (compose now uses :Z,U)
podman-compose build --no-cache
podman-compose up -d
```
If SELinux is enforcing and issues persist:
```bash
ls -ldZ data
podman unshare chown -R 0:0 data
```
### Port already in use ### Port already in use
Edit `docker-compose.yml` and change port mapping: Edit `docker-compose.yml` and change port mapping:
```yaml ```yaml
@@ -248,4 +343,4 @@ chmod 755 data
For issues or questions: For issues or questions:
- GitHub: https://github.com/nmemmert/budget - GitHub: https://github.com/nmemmert/budget
- Check logs: `docker-compose logs -f` - Check logs: `podman-compose logs -f`
+18 -5
View File
@@ -59,7 +59,7 @@ A modern, privacy-focused envelope budgeting application built with Next.js, Typ
## Getting Started ## Getting Started
### Docker Installation (Recommended for ZimaOS) ### Container Installation (Recommended for Rocky Linux + Cockpit)
**Option 1: Clone and Deploy** (works for private/public repos) **Option 1: Clone and Deploy** (works for private/public repos)
@@ -77,6 +77,19 @@ curl -fsSL https://raw.githubusercontent.com/nmemmert/budget/master/install.sh |
**Access at:** `http://localhost:7654` or `http://your-device-ip:7654` **Access at:** `http://localhost:7654` or `http://your-device-ip:7654`
### Rocky Linux + Cockpit + Podman
```bash
sudo dnf install -y podman podman-compose cockpit cockpit-podman git
sudo systemctl enable --now cockpit.socket
git clone https://github.com/nmemmert/budget.git capsule-budget
cd capsule-budget
./deploy.sh
```
Manage the container in Cockpit at `https://your-server:9090` under **Podman Containers**.
### Manual Installation (Development) ### Manual Installation (Development)
If you want to run from source: If you want to run from source:
@@ -304,19 +317,19 @@ Date,Amount,Description,Category
## Deployment ## Deployment
### ZimaOS Deployment (Recommended) ### Self-Hosted Deployment (Recommended)
Capsule is designed for self-hosted deployment on ZimaOS and similar platforms. Capsule is designed for self-hosted deployment on Rocky Linux, ZimaOS, and similar platforms.
**Quick Deploy:** **Quick Deploy:**
```bash ```bash
./deploy.sh ./deploy.sh
``` ```
See [DEPLOYMENT.md](./DEPLOYMENT.md) for detailed ZimaOS deployment instructions. See [DEPLOYMENT.md](./DEPLOYMENT.md) for detailed Podman/Docker deployment instructions.
**Features:** **Features:**
- Docker containerization for easy deployment - Podman/Docker containerization for easy deployment
- Persistent data storage in `./data` directory - Persistent data storage in `./data` directory
- Health checks and auto-restart - Health checks and auto-restart
- Encrypted local storage (no cloud required) - Encrypted local storage (no cloud required)
+22 -16
View File
@@ -7,18 +7,22 @@ set -e
echo "🚀 Deploying Capsule to ZimaOS..." echo "🚀 Deploying Capsule to ZimaOS..."
echo "" echo ""
# Detect docker compose command # Detect container compose command (Podman first, then Docker)
if command -v docker-compose &> /dev/null; then if command -v podman-compose &> /dev/null; then
DOCKER_COMPOSE="docker-compose" CONTAINER_COMPOSE="podman-compose"
elif docker compose version &> /dev/null 2>&1; then elif command -v podman &> /dev/null && podman compose version &> /dev/null 2>&1; then
DOCKER_COMPOSE="docker compose" CONTAINER_COMPOSE="podman compose"
elif command -v docker-compose &> /dev/null; then
CONTAINER_COMPOSE="docker-compose"
elif command -v docker &> /dev/null && docker compose version &> /dev/null 2>&1; then
CONTAINER_COMPOSE="docker compose"
else else
echo "❌ Docker Compose not found" echo "❌ No supported compose command found"
echo "Please install Docker Compose: https://docs.docker.com/compose/install/" echo "Install one of: podman-compose, podman compose, docker-compose, docker compose"
exit 1 exit 1
fi fi
echo "✅ Using: $DOCKER_COMPOSE" echo "✅ Using: $CONTAINER_COMPOSE"
echo "" echo ""
# Check if .env file exists # Check if .env file exists
@@ -59,17 +63,19 @@ fi
# Clear test data # Clear test data
echo "🧹 Clearing test data..." echo "🧹 Clearing test data..."
mkdir -p data
chmod 0777 data || true
rm -rf data/* rm -rf data/*
echo "✅ Test data cleared" echo "✅ Test data cleared"
echo "" echo ""
# Build and start containers # Build and start containers
echo "🔨 Building Docker image..." echo "🔨 Building container image..."
$DOCKER_COMPOSE build $CONTAINER_COMPOSE build
echo "" echo ""
echo "🚀 Starting Capsule..." echo "🚀 Starting Capsule..."
$DOCKER_COMPOSE up -d $CONTAINER_COMPOSE up -d
echo "" echo ""
echo "⏳ Waiting for container to start..." echo "⏳ Waiting for container to start..."
@@ -78,7 +84,7 @@ sleep 5
# Verify data directory is mounted # Verify data directory is mounted
echo "" echo ""
echo "🔍 Verifying data persistence..." echo "🔍 Verifying data persistence..."
if $DOCKER_COMPOSE exec capsule ls -la /app/data >/dev/null 2>&1; then if $CONTAINER_COMPOSE exec capsule ls -la /app/data >/dev/null 2>&1; then
echo "✅ Data directory is correctly mounted in container" echo "✅ Data directory is correctly mounted in container"
else else
echo "⚠️ Warning: Could not verify data directory mount" echo "⚠️ Warning: Could not verify data directory mount"
@@ -92,10 +98,10 @@ echo " http://localhost:7654"
echo " http://$(hostname -I | awk '{print $1}'):7654" echo " http://$(hostname -I | awk '{print $1}'):7654"
echo "" echo ""
echo "🔧 Useful commands:" echo "🔧 Useful commands:"
echo " $DOCKER_COMPOSE logs -f # View logs" echo " $CONTAINER_COMPOSE logs -f # View logs"
echo " $DOCKER_COMPOSE stop # Stop container" echo " $CONTAINER_COMPOSE stop # Stop container"
echo " $DOCKER_COMPOSE restart # Restart container" echo " $CONTAINER_COMPOSE restart # Restart container"
echo " $DOCKER_COMPOSE down # Stop and remove container" echo " $CONTAINER_COMPOSE down # Stop and remove container"
echo "" echo ""
echo "💾 Your data is stored in: ./data/" echo "💾 Your data is stored in: ./data/"
echo " - This directory persists across container restarts" echo " - This directory persists across container restarts"
+1 -1
View File
@@ -8,7 +8,7 @@ services:
- "7654:7654" - "7654:7654"
volumes: volumes:
# Persist user data outside container # Persist user data outside container
- ./data:/app/data - ./data:/app/data:Z,U
environment: environment:
- NODE_ENV=production - NODE_ENV=production
# Generate a secure key: openssl rand -base64 32 # Generate a secure key: openssl rand -base64 32
+36 -24
View File
@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# Capsule Budget - One-Line Installer for ZimaOS/Docker # Capsule Budget - One-Line Installer for ZimaOS/Podman/Docker
# Usage: curl -fsSL https://raw.githubusercontent.com/nmemmert/budget/master/install.sh | bash # Usage: curl -fsSL https://raw.githubusercontent.com/nmemmert/budget/master/install.sh | bash
set -e set -e
@@ -16,25 +16,36 @@ echo "║ ║"
echo "╚════════════════════════════════════════════════════════════╝" echo "╚════════════════════════════════════════════════════════════╝"
echo "" echo ""
# Check for Docker # Check for container engine
echo "🔍 Checking prerequisites..." echo "🔍 Checking prerequisites..."
if ! command -v docker &> /dev/null; then if command -v podman &> /dev/null; then
echo "❌ Docker is not installed" CONTAINER_ENGINE="podman"
echo "Please install Docker first: https://docs.docker.com/get-docker/" echo "✅ Podman found"
elif command -v docker &> /dev/null; then
CONTAINER_ENGINE="docker"
echo "✅ Docker found"
else
echo "❌ No supported container engine found"
echo "Install Podman (recommended on Rocky Linux) or Docker"
exit 1 exit 1
fi fi
echo "✅ Docker found"
# Check for Docker Compose # Check for compose command (Podman first)
if command -v docker-compose &> /dev/null; then if command -v podman-compose &> /dev/null; then
DOCKER_COMPOSE="docker-compose" CONTAINER_COMPOSE="podman-compose"
echo "✅ Docker Compose found (standalone)" echo "✅ podman-compose found"
elif docker compose version &> /dev/null 2>&1; then elif command -v podman &> /dev/null && podman compose version &> /dev/null 2>&1; then
DOCKER_COMPOSE="docker compose" CONTAINER_COMPOSE="podman compose"
echo "✅ Docker Compose found (plugin)" echo "✅ podman compose found"
elif command -v docker-compose &> /dev/null; then
CONTAINER_COMPOSE="docker-compose"
echo "✅ docker-compose found"
elif command -v docker &> /dev/null && docker compose version &> /dev/null 2>&1; then
CONTAINER_COMPOSE="docker compose"
echo "✅ docker compose found"
else else
echo "❌ Docker Compose is not installed" echo "❌ No supported compose command found"
echo "Please install Docker Compose: https://docs.docker.com/compose/install/" echo "Install one of: podman-compose, podman compose, docker-compose, docker compose"
exit 1 exit 1
fi fi
@@ -127,23 +138,24 @@ fi
# Create data directory # Create data directory
mkdir -p data mkdir -p data
chmod 0777 data || true
echo "✅ Data directory created" echo "✅ Data directory created"
# Build and start # Build and start
echo "" echo ""
echo "🔨 Building Docker image..." echo "🔨 Building container image..."
$DOCKER_COMPOSE build $CONTAINER_COMPOSE build
echo "" echo ""
echo "🚀 Starting Capsule Budget..." echo "🚀 Starting Capsule Budget..."
$DOCKER_COMPOSE up -d $CONTAINER_COMPOSE up -d
# Wait for container # Wait for container
echo "⏳ Waiting for container to start..." echo "⏳ Waiting for container to start..."
sleep 5 sleep 5
# Verify container is running # Verify container is running
if $DOCKER_COMPOSE ps | grep -q "Up"; then if $CONTAINER_COMPOSE ps | grep -q "Up"; then
echo "" echo ""
echo "╔════════════════════════════════════════════════════════════╗" echo "╔════════════════════════════════════════════════════════════╗"
echo "║ ║" echo "║ ║"
@@ -164,10 +176,10 @@ if $DOCKER_COMPOSE ps | grep -q "Up"; then
echo "💾 Data storage: $(pwd)/data" echo "💾 Data storage: $(pwd)/data"
echo "" echo ""
echo "🔧 Useful commands (run from $(pwd)):" echo "🔧 Useful commands (run from $(pwd)):"
echo " $DOCKER_COMPOSE logs -f # View logs" echo " $CONTAINER_COMPOSE logs -f # View logs"
echo " $DOCKER_COMPOSE stop # Stop Capsule" echo " $CONTAINER_COMPOSE stop # Stop Capsule"
echo " $DOCKER_COMPOSE restart # Restart Capsule" echo " $CONTAINER_COMPOSE restart # Restart Capsule"
echo " $DOCKER_COMPOSE down # Stop and remove" echo " $CONTAINER_COMPOSE down # Stop and remove"
echo "" echo ""
echo "📚 Documentation:" echo "📚 Documentation:"
echo " • README.md - Getting started guide" echo " • README.md - Getting started guide"
@@ -180,7 +192,7 @@ else
echo "❌ Container failed to start" echo "❌ Container failed to start"
echo "" echo ""
echo "Troubleshooting:" echo "Troubleshooting:"
echo "1. Check logs: $DOCKER_COMPOSE logs" echo "1. Check logs: $CONTAINER_COMPOSE logs"
echo "2. Verify .env file has ENCRYPTION_KEY set" echo "2. Verify .env file has ENCRYPTION_KEY set"
echo "3. Check if port 7654 is available" echo "3. Check if port 7654 is available"
echo "" echo ""
+6
View File
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactCompiler: true,
};
export default nextConfig;
-8
View File
@@ -1,8 +0,0 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
reactCompiler: true,
};
export default nextConfig;