Skip to main content

Database Configuration

SQLite Database Setup

The CS Library Kiosk uses SQLite3 as its primary database (as implemented in the current system).
While the SRS mentions MySQL/MariaDB for production, the current implementation uses SQLite for simplicity and reliability on Raspberry Pi hardware.

Database Initialization

1

Create Database Structure

The database is automatically initialized when you run the seeder:
cd /opt/cs-library-kiosk
source venv/bin/activate
python3 mock_data.py
This creates cs_library.db with the following tables:
  • users - Student and admin accounts
  • books - Library catalog
  • loans - Checkout/return transactions
2

Verify Database Creation

# Check database file exists
ls -lh cs_library.db

# Inspect database schema
sqlite3 cs_library.db ".schema"
3

View Test Accounts

The seeder creates these test accounts:
NameEmailStudent IDPassword
Kenneth[email protected]12345(hashed)
Jose[email protected]11111(hashed)
Professor[email protected]99999(hashed)

Database Schema Details

The database.py module implements the following schema:

Users Table

CREATE TABLE IF NOT EXISTS users (
    id            INTEGER PRIMARY KEY AUTOINCREMENT,
    student_id    TEXT    NOT NULL UNIQUE,
    name          TEXT    NOT NULL,
    email         TEXT    NOT NULL UNIQUE COLLATE NOCASE,
    password_hash TEXT    NOT NULL,
    active        INTEGER NOT NULL DEFAULT 1,
    created_at    DATETIME DEFAULT CURRENT_TIMESTAMP
);

Books Table

CREATE TABLE IF NOT EXISTS books (
    isbn    TEXT PRIMARY KEY,
    title   TEXT NOT NULL,
    author  TEXT NOT NULL,
    cover   TEXT NOT NULL DEFAULT "",
    status  TEXT NOT NULL DEFAULT "Available",
    shelf   TEXT NOT NULL DEFAULT ""
);

Loans Table

CREATE TABLE IF NOT EXISTS loans (
    id            INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id       INTEGER NOT NULL REFERENCES users(id),
    isbn          TEXT    NOT NULL REFERENCES books(isbn),
    checked_out   DATETIME DEFAULT CURRENT_TIMESTAMP,
    due_date      DATETIME NOT NULL,
    returned      INTEGER  NOT NULL DEFAULT 0,
    returned_date DATETIME
);

Database Configuration in Code

The database path is configured in database.py:13:
DB_PATH = Path(__file__).parent / "cs_library.db"
To use a different location:
# Option 1: Environment variable
import os
DB_PATH = Path(os.getenv('DB_PATH', '/var/lib/cs-library/cs_library.db'))

# Option 2: Absolute path
DB_PATH = Path('/opt/cs-library-kiosk/data/cs_library.db')

Environment Variables

Creating Environment Configuration

Create a .env file for environment-specific settings:
1

Create .env file

cd /opt/cs-library-kiosk
vim .env
2

Add Configuration Variables

# Application Settings
APP_HOST=0.0.0.0
APP_PORT=8080
APP_TITLE="CS Library Kiosk"

# Database Configuration
DB_PATH=/opt/cs-library-kiosk/cs_library.db

# Open Library API Settings
USE_LIVE_API=True
API_USER_AGENT="SCSU_CS_Library_Kiosk/1.0 ([email protected])"
API_TIMEOUT=8.0

# Session Settings
SESSION_TIMEOUT=900  # 15 minutes in seconds

# Checkout Settings
LOAN_PERIOD_DAYS=14
MAX_RENEWALS=2

# Logging
LOG_LEVEL=INFO
LOG_FILE=/var/log/cs-library-kiosk/app.log
3

Secure the .env file

chmod 600 .env
chown pi:pi .env
Never commit .env files to version control. Add .env to .gitignore.
4

Load Environment Variables

The application already uses python-dotenv (in requirements.txt:33).Add to your main.py:
from dotenv import load_dotenv
import os

# Load environment variables
load_dotenv()

# Access variables
HOST = os.getenv('APP_HOST', '0.0.0.0')
PORT = int(os.getenv('APP_PORT', '8080'))

Network Configuration

For production deployment, configure a static IP address:
1

Edit dhcpcd configuration

sudo vim /etc/dhcpcd.conf
2

Add static IP configuration

Add at the end of the file:
# Static IP for CS Library Kiosk
interface eth0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1 8.8.8.8
Adjust the IP address, gateway, and DNS servers according to your network configuration.
3

Restart networking

sudo systemctl restart dhcpcd

# Verify new IP
ip addr show eth0

Firewall Configuration

1

Install UFW (Uncomplicated Firewall)

sudo apt install -y ufw
2

Configure firewall rules

# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH (for remote management)
sudo ufw allow 22/tcp

# Allow kiosk web interface
sudo ufw allow 8080/tcp

# Optional: Allow from specific IP range only
# sudo ufw allow from 192.168.1.0/24 to any port 8080

# Enable firewall
sudo ufw enable
3

Check firewall status

sudo ufw status verbose

DNS and API Access

Ensure the kiosk can reach the Open Library API:
# Test DNS resolution
nslookup openlibrary.org

# Test HTTPS connectivity
curl -I https://openlibrary.org/api/books?bibkeys=ISBN:9780140328721&format=json&jscmd=data

# Test from Python
python3 -c "import httpx; print(httpx.get('https://openlibrary.org').status_code)"

Backup Procedures

Automated Database Backups

Per SRS Section 4.3, the system requires daily automated database backups to protect against SD card corruption.
1

Create backup directory

sudo mkdir -p /var/backups/cs-library-kiosk
sudo chown pi:pi /var/backups/cs-library-kiosk
2

Create backup script

sudo vim /usr/local/bin/backup-cs-library.sh
Add the following:
#!/bin/bash

# CS Library Kiosk Backup Script
BACKUP_DIR="/var/backups/cs-library-kiosk"
DB_PATH="/opt/cs-library-kiosk/cs_library.db"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/cs_library_$TIMESTAMP.db"

# Create backup
sqlite3 "$DB_PATH" ".backup '$BACKUP_FILE'"

# Compress backup
gzip "$BACKUP_FILE"

# Keep only last 30 days of backups
find "$BACKUP_DIR" -name "cs_library_*.db.gz" -mtime +30 -delete

# Log backup
echo "$(date): Backup completed - $BACKUP_FILE.gz" >> /var/log/cs-library-backup.log
3

Make script executable

sudo chmod +x /usr/local/bin/backup-cs-library.sh
4

Schedule daily backups with cron

sudo crontab -e
Add the following line to run backup daily at 2 AM:
0 2 * * * /usr/local/bin/backup-cs-library.sh
5

Test backup script

sudo /usr/local/bin/backup-cs-library.sh

# Verify backup created
ls -lh /var/backups/cs-library-kiosk/
For additional protection against SD card failure:
1

Mount USB drive

# Identify USB device
lsblk

# Create mount point
sudo mkdir -p /mnt/usb-backup

# Mount USB drive (adjust device as needed)
sudo mount /dev/sda1 /mnt/usb-backup
2

Configure automatic mounting

# Get UUID of USB drive
sudo blkid /dev/sda1

# Edit fstab
sudo vim /etc/fstab
Add line (replace UUID):
UUID=XXXX-XXXX /mnt/usb-backup vfat defaults,nofail 0 0
3

Create USB backup script

sudo vim /usr/local/bin/backup-to-usb.sh
#!/bin/bash

# Sync database backups to USB
rsync -av --delete \
  /var/backups/cs-library-kiosk/ \
  /mnt/usb-backup/cs-library-backups/

# Also backup the entire application
rsync -av --exclude='venv' --exclude='__pycache__' \
  /opt/cs-library-kiosk/ \
  /mnt/usb-backup/cs-library-app/
sudo chmod +x /usr/local/bin/backup-to-usb.sh
4

Schedule USB sync

Add to crontab (runs at 3 AM):
0 3 * * * /usr/local/bin/backup-to-usb.sh

Backup Restoration

To restore from a backup:
# Stop the service
sudo systemctl stop cs-library-kiosk.service

# Backup current database (just in case)
cp /opt/cs-library-kiosk/cs_library.db /tmp/cs_library_current.db

# Find backup to restore
ls -lh /var/backups/cs-library-kiosk/

# Decompress and restore
gunzip -c /var/backups/cs-library-kiosk/cs_library_20260304_020000.db.gz > /opt/cs-library-kiosk/cs_library.db

# Set proper permissions
chown pi:pi /opt/cs-library-kiosk/cs_library.db
chmod 600 /opt/cs-library-kiosk/cs_library.db

# Restart service
sudo systemctl start cs-library-kiosk.service

Application Configuration

Configuring API Integration

The Open Library API integration is configured in database.py:16:
# Enable/disable live API lookups
USE_LIVE_API = True
To disable API lookups (offline mode):
USE_LIVE_API = False
Or set via environment variable:
# In .env file
USE_LIVE_API=False

Adjusting Loan Period

Default loan period is 14 days (database.py:261, 309):
due = datetime.now() + timedelta(days=14)
To change globally, add to environment configuration:
# In .env
LOAN_PERIOD_DAYS=21
Then modify database.py:
import os
LOAN_DAYS = int(os.getenv('LOAN_PERIOD_DAYS', '14'))
due = datetime.now() + timedelta(days=LOAN_DAYS)

Performance Tuning

SQLite Optimization

Add to database connection in database.py:21-24:
def _connect() -> sqlite3.Connection:
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA foreign_keys = ON")
    
    # Performance optimizations
    conn.execute("PRAGMA journal_mode = WAL")  # Write-Ahead Logging
    conn.execute("PRAGMA synchronous = NORMAL")  # Faster writes
    conn.execute("PRAGMA cache_size = 10000")  # Increase cache
    
    return conn

Application Performance

Adjust NiceGUI settings in main.py:450:
ui.run(
    host='0.0.0.0',
    port=8080,
    title="CS Library Kiosk",
    favicon='favicon1.ico',
    dark=True,
    reload=False,  # Disable auto-reload in production
    show=False  # Don't auto-open browser
)

Logging Configuration

Application Logging

Create a logging configuration:
import logging
from logging.handlers import RotatingFileHandler
import os

# Configure logging
log_level = os.getenv('LOG_LEVEL', 'INFO')
log_file = os.getenv('LOG_FILE', '/var/log/cs-library-kiosk/app.log')

# Create log directory if needed
os.makedirs(os.path.dirname(log_file), exist_ok=True)

# Configure logger
logging.basicConfig(
    level=getattr(logging, log_level),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        RotatingFileHandler(log_file, maxBytes=10485760, backupCount=5),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

Log Rotation

Configure logrotate:
sudo vim /etc/logrotate.d/cs-library-kiosk
/var/log/cs-library-kiosk/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 pi pi
    sharedscripts
    postrotate
        systemctl reload cs-library-kiosk.service > /dev/null 2>&1 || true
    endscript
}

Monitoring and Alerts

System Health Monitoring

Create a health check script:
sudo vim /usr/local/bin/health-check.sh
#!/bin/bash

# Check if service is running
if ! systemctl is-active --quiet cs-library-kiosk.service; then
    echo "ALERT: CS Library Kiosk service is not running" | \
      logger -t cs-library-health
    # Attempt restart
    systemctl restart cs-library-kiosk.service
fi

# Check database accessibility
if ! sqlite3 /opt/cs-library-kiosk/cs_library.db "SELECT 1" > /dev/null 2>&1; then
    echo "ALERT: Database is not accessible" | \
      logger -t cs-library-health
fi

# Check disk space
USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $USAGE -gt 90 ]; then
    echo "ALERT: Disk usage is at ${USAGE}%" | \
      logger -t cs-library-health
fi

# Check temperature
TEMP=$(vcgencmd measure_temp | sed 's/temp=//' | sed 's/.C//')
if (( $(echo "$TEMP > 80" | bc -l) )); then
    echo "ALERT: CPU temperature is ${TEMP}°C" | \
      logger -t cs-library-health
fi
sudo chmod +x /usr/local/bin/health-check.sh

# Run every 5 minutes
*/5 * * * * /usr/local/bin/health-check.sh

Security Configuration

Database Security

# Set restrictive permissions on database
chmod 600 /opt/cs-library-kiosk/cs_library.db
chown pi:pi /opt/cs-library-kiosk/cs_library.db

# Prevent accidental deletion
sudo chattr +i /opt/cs-library-kiosk/cs_library.db
# (Use 'sudo chattr -i' to unlock when needed)

Password Security

The system uses bcrypt for password hashing (requirements.txt:50, database.py:80):
  • Passwords are hashed with bcrypt salt rounds
  • Never stored in plain text
  • Verified using secure comparison

Input Validation

Ensure all user inputs are validated:
  • ISBN format validation (10 or 13 digits)
  • Student ID format validation
  • SQL injection prevention (parameterized queries used throughout)
  • XSS prevention (NiceGUI handles escaping)

Production Checklist

1

Database

Database initialized with schema
Test accounts created or removed
Database file permissions set (600)
Backup scripts configured and tested
2

Network

Static IP configured (if required)
Firewall rules enabled
DNS resolution working
Open Library API accessible
3

Application

Systemd service enabled and running
Environment variables configured
Logging configured and rotating
Auto-start on boot tested
4

Security

Default passwords changed
SSH key-based auth enabled
Unnecessary services disabled
File permissions restricted
5

Monitoring

Health check script running
Backup verification successful
Log rotation configured
Temperature monitoring active

Troubleshooting

Database Locked Errors

# Check for lingering processes
lsof /opt/cs-library-kiosk/cs_library.db

# If using WAL mode, check for wal files
ls -la /opt/cs-library-kiosk/cs_library.db*

# Clear WAL checkpoint
sqlite3 /opt/cs-library-kiosk/cs_library.db "PRAGMA wal_checkpoint(FULL);"

Service Fails to Start

# Check logs
sudo journalctl -u cs-library-kiosk.service -n 50

# Verify file paths in service file
sudo systemctl cat cs-library-kiosk.service

# Test manually
cd /opt/cs-library-kiosk
source venv/bin/activate
python3 main.py

API Timeouts

# Test API connectivity
curl -m 10 https://openlibrary.org/api/books?bibkeys=ISBN:9780140328721&format=json

# Adjust timeout in database.py:146
async with httpx.AsyncClient(timeout=15.0) as client:

Next Steps

With your system fully configured:
  1. Test all workflows (checkout, return, search, renewals)
  2. Load production data and remove test accounts
  3. Perform user acceptance testing
  4. Document any custom configurations
  5. Train staff on system operation and maintenance

Build docs developers (and LLMs) love