Skip to main content

Installation Guide

This guide covers comprehensive installation and configuration for both development and production environments of the SWL Library Management System.
For a quick development setup, see the Quick Start Guide. This guide focuses on production-ready installations.

System Requirements

Minimum Requirements

Python

Python 3.8 or higherVerify: python --version

Memory

512 MB RAM minimum1 GB+ recommended for production

Storage

100 MB for applicationAdditional space for database growth

Operating System

Linux, macOS, or WindowsLinux recommended for production

Production Requirements

For production deployments, you’ll also need:
  • PostgreSQL 12+ (recommended) or SQLite 3.x
  • Web server: Nginx or Apache for reverse proxy
  • WSGI server: Gunicorn (Linux/macOS) or Waitress (Windows)
  • SSL certificate for HTTPS (Let’s Encrypt recommended)
  • Process manager: systemd or supervisor

Installation Steps

1

Install Python Dependencies

First, ensure Python 3.8+ and pip are installed:
sudo apt update
sudo apt install python3 python3-pip python3-venv
Verify installation:
python --version  # or python3 --version
pip --version
2

Clone the Repository

Get the SWL source code:
git clone https://github.com/your-username/Sistema-Gestion-Bibliotecaria.git
cd Sistema-Gestion-Bibliotecaria
For production, consider cloning to /opt/swl or /var/www/swl for better organization.
3

Create Virtual Environment

Always use a virtual environment to isolate dependencies:
python3 -m venv venv
source venv/bin/activate
Critical for production: Never install dependencies globally. Virtual environments prevent version conflicts and system contamination.
Verify activation:
which python  # Should show path inside venv/
4

Install Python Packages

Install all required dependencies from requirements.txt:
python -m pip install --upgrade pip
pip install -r requirements.txt
This installs 30+ packages including:Core Framework:
  • Flask 3.1.3 - Web framework
  • Werkzeug 3.1.6 - WSGI utilities
  • Jinja2 3.1.6 - Template engine
Database & ORM:
  • SQLAlchemy 2.0.47 - ORM
  • Flask-SQLAlchemy 3.1.1 - Flask integration
  • Flask-Migrate 4.1.0 - Database migrations
  • alembic 1.18.4 - Migration tool
Authentication:
  • Flask-Login 0.6.3 - Session management
  • Flask-WTF 1.2.2 - Form handling
  • WTForms 3.2.1 - Form validation
Scheduled Tasks:
  • Flask-APScheduler 1.13.1 - Cron jobs
  • APScheduler 3.11.2 - Task scheduler
Data Processing:
  • pandas 3.0.1 - Excel import/export
  • openpyxl 3.1.5 - Excel file handling
  • numpy 2.4.2 - Numerical operations
Installation takes 2-3 minutes. For faster installs, use a package cache or pip mirror.
5

Configure Environment Variables

Create a .env file for production configuration:
touch .env
Add your configuration:
.env
# Security
SECRET_KEY=your-very-secure-random-key-here-change-this

# Database (PostgreSQL)
DATABASE_URL=postgresql://username:password@localhost/swl_db

# Business Configuration
PENALTY_FEE_PER_DAY=5000.0

# Application
FLASK_ENV=production
FLASK_DEBUG=0
Never commit .env to version control! Add it to .gitignore:
echo ".env" >> .gitignore
Generate a secure secret key:
python -c "import secrets; print(secrets.token_hex(32))"

Database Setup

Option 1: SQLite (Development)

SQLite is perfect for development and small deployments (< 100 concurrent users). It requires no separate database server.
SQLite is configured by default in config.py:10-11:
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
    'sqlite:///' + os.path.join(basedir, 'instance', 'app.db')
The database file is automatically created at instance/app.db on first run. Initialization:
python run.py
This will:
  1. Create instance/app.db
  2. Initialize all tables
  3. Create the default admin account
  4. Seed sample inventory

Option 2: PostgreSQL (Production)

Recommended for production due to better concurrency, performance, and reliability.
1

Install PostgreSQL

sudo apt install postgresql postgresql-contrib
sudo systemctl start postgresql
sudo systemctl enable postgresql
2

Create Database and User

sudo -u postgres psql
In the PostgreSQL shell:
CREATE DATABASE swl_db;
CREATE USER swl_user WITH PASSWORD 'your_secure_password';
GRANT ALL PRIVILEGES ON DATABASE swl_db TO swl_user;
\q
3

Install Python PostgreSQL Driver

pip install psycopg2-binary
4

Configure Database URL

Set the DATABASE_URL environment variable in .env:
DATABASE_URL=postgresql://swl_user:your_secure_password@localhost/swl_db
Or export it directly:
export DATABASE_URL="postgresql://swl_user:your_secure_password@localhost/swl_db"
5

Initialize Database

Run the application to create tables:
python run.py
The db.create_all() call in run.py:8 creates all tables:
with app.app_context():
    db.create_all()  # Creates User, Catalog, ItemInstance, Loan, LibraryLog

Database Migrations (Advanced)

For production deployments, use Flask-Migrate for schema changes:
# Initialize migrations (first time only)
flask db init

# Create migration after model changes
flask db migrate -m "Description of changes"

# Apply migration
flask db upgrade
Migrations are stored in migrations/versions/ and tracked in version control.

Configuration Deep Dive

The config.py file contains all application settings:

Security Configuration

config.py
class Config:
    # Change this in production!
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'clave-secreta-para-desarrollo'
    
    # Session timeout (30 minutes)
    PERMANENT_SESSION_LIFETIME = timedelta(minutes=30)
Production Security Checklist:
  • Set SECRET_KEY via environment variable
  • Use strong, randomly generated keys (32+ characters)
  • Never commit secrets to git
  • Rotate keys periodically

Database Configuration

config.py
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
    'sqlite:///' + os.path.join(basedir, 'instance', 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False  # Reduces overhead

Scheduler Configuration

config.py
SCHEDULER_API_ENABLED = False  # Disable API for security
SCHEDULER_TIMEZONE = "America/Bogota"  # Adjust to your timezone
Change SCHEDULER_TIMEZONE to match your location. Common values:
  • "America/New_York"
  • "Europe/London"
  • "Asia/Tokyo"
  • "UTC" (recommended for international deployments)

Business Logic Configuration

config.py
# Penalty fee per day of late return (in your currency)
PENALTY_FEE_PER_DAY = float(os.environ.get('PENALTY_FEE_PER_DAY', 5000.0))

# Application branding
APP_NAME = "SWL"
LIBRARY_NAME = "SWL"

# User role definitions
USER_ROLES = {
    'admin': 'Administrador del Sistema',
    'bibliotecario': 'Bibliotecario / Staff',
    'premium': 'Usuario Premium',
    'cliente': 'Estudiante / Cliente Regular'
}
Customize these values via environment variables:
.env
PENALTY_FEE_PER_DAY=10.00  # $10 per day in USD

Logging Configuration

config.py
LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logs', 'library.log')
Logs are written to logs/library.log with rotation (from app/__init__.py:49):
file_handler = RotatingFileHandler(
    app.config['LOG_FILE'], 
    maxBytes=1024000,  # 1 MB
    backupCount=3       # Keep 3 old versions
)
Log format:
2026-03-04 15:23:10,123 INFO: User admin logged in [in app/auth/routes.py:21]

Production Deployment

Using Gunicorn (Linux/macOS)

1

Install Gunicorn

pip install gunicorn
2

Create WSGI Entry Point

Create wsgi.py in the project root:
wsgi.py
from app import create_app, db

app = create_app()

if __name__ == "__main__":
    app.run()
3

Run Gunicorn

gunicorn -w 4 -b 0.0.0.0:5000 wsgi:app
Parameters:
  • -w 4: 4 worker processes (adjust based on CPU cores)
  • -b 0.0.0.0:5000: Bind to all interfaces on port 5000
  • wsgi:app: Import app from wsgi.py
Worker calculation: Use (2 × CPU_cores) + 1. For 2 cores: -w 5
4

Create Systemd Service

For automatic startup, create /etc/systemd/system/swl.service:
[Unit]
Description=SWL Library Management System
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/opt/swl
Environment="PATH=/opt/swl/venv/bin"
ExecStart=/opt/swl/venv/bin/gunicorn -w 4 -b 127.0.0.1:5000 wsgi:app
Restart=always

[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable swl
sudo systemctl start swl
sudo systemctl status swl

Using Waitress (Windows)

pip install waitress
Create serve.py:
serve.py
from waitress import serve
from app import create_app

app = create_app()
serve(app, host='0.0.0.0', port=5000, threads=4)
Run:
python serve.py

Nginx Reverse Proxy

Create /etc/nginx/sites-available/swl:
server {
    listen 80;
    server_name your-domain.com;
    
    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    location /static {
        alias /opt/swl/app/static;
        expires 30d;
    }
}
Enable and reload:
sudo ln -s /etc/nginx/sites-available/swl /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

SSL with Let’s Encrypt

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
Auto-renewal is configured automatically.

Deployment Checklist

  • Set strong SECRET_KEY via environment variable
  • Change default admin password (1000000000 / admin123)
  • Use PostgreSQL instead of SQLite
  • Enable HTTPS with valid SSL certificate
  • Set FLASK_DEBUG=0 in production
  • Configure firewall (allow only 80/443)
  • Run application as non-root user (www-data)
  • Set proper file permissions (chmod 600 .env)
  • Disable directory listing in web server
  • Implement rate limiting (Flask-Limiter)
  • Use PostgreSQL for production
  • Configure Gunicorn with appropriate workers
  • Enable Nginx gzip compression
  • Set up static file caching
  • Configure database connection pooling
  • Add database indexes for frequent queries
  • Monitor application logs for slow queries
  • Set up log rotation for disk space
  • Daily automated database backups
  • Test restore procedures regularly
  • Back up .env file (securely)
  • Version control for code (Git)
  • Off-site backup storage
  • Document backup/restore procedures
  • Configure log rotation (done automatically)
  • Set up log aggregation (Sentry, Papertrail)
  • Monitor disk space for database growth
  • Set up uptime monitoring (UptimeRobot)
  • Configure error notifications
  • Monitor scheduled task execution
  • Track application metrics (users, loans, etc.)

Troubleshooting

Common Installation Issues

Problem: Some packages require compilation (psycopg2, numpy)Solution: Install system development tools:
# Ubuntu/Debian
sudo apt install build-essential python3-dev libpq-dev

# CentOS/RHEL
sudo yum install gcc python3-devel postgresql-devel
Or use binary wheels:
pip install psycopg2-binary  # Instead of psycopg2
PostgreSQL connection refused:
  1. Check PostgreSQL is running:
sudo systemctl status postgresql
  1. Verify connection settings in DATABASE_URL
  2. Check PostgreSQL listens on correct interface (/etc/postgresql/.../postgresql.conf):
listen_addresses = 'localhost'
  1. Verify pg_hba.conf allows connections:
local   all   all   md5
  1. Test connection:
psql -U swl_user -d swl_db -h localhost
Problem: Can’t write to instance/app.dbSolution: Ensure proper permissions:
mkdir -p instance logs
chmod 755 instance logs
chown www-data:www-data instance logs  # If running as www-data
Problem: Overdue loan checks don’t executeSolution:
  1. Verify scheduler is enabled (app/__init__.py:28):
scheduler.init_app(app)
scheduler.start()
  1. Check logs for scheduler errors:
tail -f logs/library.log | grep actualizar_moras
  1. Ensure timezone is correct in config.py
  2. Test manually:
from app import create_app
from app.services.loan_service import LoanService

app = create_app()
with app.app_context():
    LoanService.check_overdue_loans()
Problem: CSS/JS files return 404Solution:
  1. Verify static directory exists: app/static/
  2. Check Nginx configuration serves static files
  3. Ensure correct permissions:
chmod -R 755 app/static

Database Issues

Reset database (development only):
# SQLite
rm instance/app.db
python run.py

# PostgreSQL
psql -U postgres
DROP DATABASE swl_db;
CREATE DATABASE swl_db;
GRANT ALL PRIVILEGES ON DATABASE swl_db TO swl_user;
\q
python run.py
Never reset the production database! This deletes all data permanently.
Check database contents:
# SQLite
sqlite3 instance/app.db
.tables
SELECT * FROM user;
.quit

# PostgreSQL
psql -U swl_user -d swl_db
\dt
SELECT * FROM "user";
\q

Next Steps

Configuration Guide

Detailed configuration options and customization

User Management

Creating users, roles, and permissions

Inventory Setup

Adding catalog items and equipment

API Reference

Explore models, services, and routes

Getting Help

If you encounter issues not covered here:
  1. Check the application logs: logs/library.log
  2. Review error messages carefully
  3. Search existing GitHub issues
  4. Create a new issue with:
    • Python version
    • Operating system
    • Full error traceback
    • Steps to reproduce
For production support and custom deployments, consider professional services or community forums.

Build docs developers (and LLMs) love