Table of Contents

Admin Guide
Community Edition | Enterprise Edition


Configuring SWIRL AI Search

Configuring the Environment

SWIRL uses django-environ to load critical settings from a file named .env.

  • The .env.dist file contains default settings.
  • If no .env file exists, the install.sh script copies .env.dist to .env.

Example .env File:

SECRET_KEY=your-secret-key
ALLOWED_HOSTS=localhost
PROTOCOL=http
SWIRL_EXPLAIN=True
SQL_ENGINE=django.db.backends.sqlite3
SQL_DATABASE=db.sqlite3
SQL_USER=user
SQL_PASSWORD=password
SQL_HOST=localhost
SQL_PORT=5432
MICROSOFT_CLIENT_ID=''
MICROSOFT_CLIENT_SECRET=''
MICROSOFT_REDIRECT_URI=''
OPENAI_API_KEY=

Making Changes to .env

To configure hostname, protocol, or port:

  1. Edit the .env file.
  2. Restart SWIRL for changes to take effect.

There should never be a .env file in the SWIRL repo. When upgrading SWIRL, these settings persist automatically.

Environment Variable Descriptions

Creating a SWIRL Super User

To reset the database:

  1. Delete or rename the db.sqlite3 file.
  2. Run:
python swirl.py setup

This creates a new blank database.

To create a Super User, run:

python manage.py createsuperuser --email admin@example.com --username admin

Changing the Super User Password

To change the password of an existing admin user:

python manage.py changepassword admin

If the new password is too simple, Django will reject it.

For more details, see: Django Admin and manage.py

Using the Django Admin

To change the Super User password via Django Admin:

  1. Go to: http://localhost:8000/swirl
  2. Click "CHANGE PASSWORD":

    Django Admin Change Password

  3. Enter a new password:

    Django Admin Change Password

  4. Click "CHANGE MY PASSWORD".

Adding Normal Users

Users can be managed via Django Admin:

http://localhost:8000/admin/

Django Admin - Users

If using OpenID Connect, manual user creation is not required. See the AI Search Guide for details.

Permissioning Normal Users

Each SWIRL core object (SearchProviders, Search, Result, Query Transform) has four permissions:

  • add → Allows creation
  • change → Allows modification
  • delete → Allows removal
  • view → Allows read-only access

    Django Admin - Permissions

Recommended Permission Configurations

Scenario SearchProvider Search Results Query Transform
Admin ALL ALL ALL ALL
Search ONLY NONE Add    
Result ONLY NONE NONE View  
Search & View Results NONE Add, View Add, View Add, View
Manage Search (including re-run) NONE ALL ALL ALL
SearchProvider Admin ALL Add View View

Object Ownership

SearchProvider, Search, Result, and Query Transform objects are owned by the Django user who creates them and are private by default.

Shared SearchProviders and Query Transformations

  • By default, sharing is disabled (false) for all users.
  • Django Super Users (admin) have sharing enabled (true) by default.

This prevents users from needing to duplicate SearchProviders or Query Transformations.

Managing Large User Groups

For installations with many users, consider:

  1. Creating user groups with predefined permissions.
  2. Assigning users to the appropriate groups.

This simplifies access control and reduces administrative overhead.

Deploying SWIRL for Production Use

The SWIRL application is designed to be deployed behind a reverse-proxy for optimal scalability, security, performance, and availability.

**Why Use a Reverse-Proxy?**

  • Scalability:
    • Enables horizontal scaling by distributing requests across multiple SWIRL servers.
    • Dynamically provisions additional VMs when demand increases.
    • Deactivates idle VMs to reduce hosting costs.
  • Security:
    • SSL/TLS termination at the reverse-proxy reduces CPU load on the application server.
  • Performance:
    • Separates static content delivery from the application server.
    • Supports Content Delivery Networks (CDN) for faster response times.
  • Availability:
    • Load balances traffic across multiple backend SWIRL servers.
    • Monitors and removes failed servers to maintain uptime.

**Recommended Reverse-Proxy Solutions**

For deployment assistance, please contact support.

Upgrading SWIRL

For Docker upgrades, please contact support for instructions!

  1. Update the swirl-search repository:
    git pull
    
  2. Run the install script:
    ./install.sh
    
  3. Set up SWIRL:
    python swirl.py setup
    
  4. If upgrading the Galaxy UI, run:
    ./install-ui.sh
    
  5. Restart SWIRL:
    python swirl.py restart
    

Refer to the release notes for details on each update.

Resetting Prompts

To reset AI prompts to default settings, run:

python swirl.py reload_ai_prompts

This restores system prompts to factory settings while keeping custom prompts unchanged.

Configuring SWIRL

SWIRL configuration is managed in: swirl_server/settings.py

Key Configuration Items

Configuration Item Explanation Example
CELERY_BEATS_SCHEDULE Defines the schedule for the Search Expiration Service and Search Subscriber Service See linked sections
SWIRL_DEFAULT_QUERY_LANGUAGE Determines the stopword dictionary SWIRL_DEFAULT_QUERY_LANGUAGE = 'english'
SWIRL_TIMEOUT Time (in seconds) before terminating slow connectors SWIRL_TIMEOUT = 10
SWIRL_SUBSCRIBE_WAIT Timeout for updating a search SWIRL_SUBSCRIBE_WAIT = 20
SWIRL_DEDUPE_FIELD Field used for duplicate detection SWIRL_DEDUPE_FIELD = 'url'
SWIRL_DEDUPE_SIMILARITY_MINIMUM Minimum similarity score to classify as duplicate SWIRL_DEDUPE_SIMILARITY_MINIMUM = 0.95
SWIRL_DEDUPE_SIMILARITY_FIELDS Fields used for duplicate detection SWIRL_DEDUPE_SIMILARITY_FIELDS = ['title', 'body']
SWIRL_RELEVANCY_CONFIG Defines relevancy score weights for key fields See below
SWIRL_MAX_MATCHES Maximum matches per result (limits long articles) SWIRL_MAX_MATCHES = 5
SWIRL_MIN_SIMILARITY Minimum score required for query hits to be scored SWIRL_MIN_SIMILARITY = 0.54
SWIRL_EXPLAIN Enables relevancy explain structures in responses SWIRL_EXPLAIN = false

Example SWIRL_RELEVANCY_CONFIG

SWIRL_RELEVANCY_CONFIG = {
    'title': {
        'weight': 1.5
    },
    'body': {
        'weight': 1.0
    },
    'author': {
        'weight': 1.0
    }
}

All configuration items must be uppercase, following the Django settings convention.

Search Expiration Service

The Expirer service automatically deletes expired Search objects and their associated Result objects. This prevents SWIRL from retaining all past searches indefinitely.

Service Frequency

SWIRL allows custom expiration settings for Search and Result objects, but the expiration service runs on a fixed schedule.

  • By default, it runs every hour.
  • The schedule is defined in the Django settings:
CELERY_BEAT_SCHEDULE = {
    # Executes every hour
    'expire': { 
         'task': 'expirer', 
         'schedule': crontab(minute=0, hour='*'),
    },          
}
  • Temporary changes can be made via the Django Admin Console:

    http://localhost:8000/admin/django_celery_beat/crontabschedule/
    

    Django console crontab page

Enterprise Edition supports a 5-minute expiration schedule. Please contact support for details.

If you modify crontab in the database without updating CELERY_BEAT_SCHEDULE, the original schedule will be restored when SWIRL restarts.

Search Subscriber Service

When a Search object has subscribe=True, SWIRL will periodically update that Search. See the Developer Guide for more details.

  • By default, the service runs every 4 hours.
  • The schedule is defined in Django settings:
CELERY_BEAT_SCHEDULE = {
    # Executes every four hours
    'subscribe': { 
         'task': 'subscriber', 
         'schedule': crontab(minute=0, hour='*/4'),   
    },          
}
  • Temporary changes can be made via the Django Admin Console:

    http://localhost:8000/admin/django_celery_beat/crontabschedule/
    

    Django console crontab page

If you modify crontab in the database without updating CELERY_BEAT_SCHEDULE, the original schedule will be restored when SWIRL restarts.

Service Startup & Daemonization

Using swirl.py

For normal operations, use swirl.py to start, stop, or restart services. This script is located in the SWIRL installation directory (next to manage.py).

**Starting Services**

python swirl.py start

To start specific services, specify them by name:

python swirl.py start celery-beats

**Checking Service Status**

python swirl.py status

Example output:

INFO 2025-03-01 19:59:55 settings Swirl Enterprise 4.1-DEV licensed to: SWIRL_Corporation

         .   o
        .        .   .  o  
        .      .                                    
  o        .  @ @   .            SWIRL AI ENTERPRISE 4.1-DEV
    .        @ @  .    .         Licensed to: SWIRL_Corporation
      .  . .   .     .    .
            .       .     o
     o  .       o .


Service: django...RUNNING, pid:34738
Service: celery-worker...RUNNING, pid:34767

  PID TTY           TIME CMD
34738 ttys005    0:56.97 /Library/Frameworks/Python.framework/Versions/3.12/Resources/Python.app/Contents/MacOS/Python /Library/Frameworks/Python.framework/Versions/3.12/bin/daphne -b 0.0.0.0 -p 8000 swirl_server.asgi:application
34767 ttys005    2:10.94 /Library/Frameworks/Python.framework/Versions/3.12/Resources/Python.app/Contents/MacOS/Python /Library/Frameworks/Python.framework/Versions/3.12/bin/celery -A swirl_server worker -Q default --without-heartbeat --without-gossip --without-mingle --loglevel=info --concurrency=15

Command successful!

**Stopping Services**

python swirl.py stop

**Restarting Services**

python swirl.py restart

To restart specific services, specify them by name:

python swirl.py restart celery-worker consumer

**Getting Help**

python swirl.py help

Customizing

The services invoked by swirl.py are defined in: swirl/services.py

Modify this list to automatically start celery-beats.

Changing the Galaxy Logos and Branding

To customize the logo, search button, and labels in SWIRL Galaxy:

  1. Go to the SWIRL Admin Page: http://localhost:8000/admin/

    SWIRL home page

  2. Click the "admin" link to open the Admin UI:

    SWIRL admin UI

  3. Click "Upload a Branding Configuration" to go to the Branding Configuration page:

    SWIRL branding configuration

  4. Fill out the form:

    • "Name" is required.
    • At least one additional field must be customized.
    • To change the logo, upload a light mode image.

Branding Configuration Options

Item Galaxy Location Default
Name Not shown N/A
Search button label Search button text SEARCH
Search bar placeholder Placeholder text in search box "What are you searching for today?"
AI Response label Below search box "Generate AI Response"
Select items label Below paging control "Select Items"
  1. Click "Submit" to save your branding changes.
  2. Refresh your browser to apply changes in Galaxy UI.

Refreshing may start a new RAG or chat session.

Logo File Requirements

  • Format: PNG
  • Dimensions: 818 × 214 px
  • Whitespace: At least 30 px margin around the logo

Only one branding configuration can be active at a time.

Managing Django Users

Django Admin

Most users can be managed through Django Admin, accessible at:

http://localhost:8000/admin/

For more details, watch this YouTube video on Django Administration.

Changing a User's Password

To change a user's password via the command line:

python manage.py changepassword <user_name>

Management Tools

Django Console

Django provides a web-based UI for managing users, groups, crontabs, and more.

Django console

Access it here: http://localhost:8000/admin/

For an in-depth tutorial, watch this YouTube playlist on Django Admin.

Django dbshell

Django has a built-in shell for direct database management. Run it inside the swirl-search directory:

./manage.py dbshell

Wiping the Database

To delete all SWIRL objects and reset the database:

python manage.py flush

This will remove all data permanently.

You must create a new SWIRL Super User after doing this.

sqlite-web

sqlite-web provides an open-source web-based GUI for SQLite.

**Installation & Usage**

pip install sqlite-web
sqlite_web my_database.db                   # Runs locally at http://localhost:8080/
sqlite_web --host 0.0.0.0 my_database.db    # Run it on the LAN

Use the full path to db.sqlite3 in swirl-search when running sqlite-web.

Database Migration

If you modify swirl/models.py, you must run a database migration.

**Basic Migration Command**

python swirl.py migrate

For more details, see: https://docs.djangoproject.com/en/4.0/topics/migrations/

**General Migration Guidelines**

  • Adding fields or changing defaults is usually simple.
  • If renaming an id or modifying relationships, consider wiping existing data first (sqlite-web can help).

**If Migration Fails**

  1. Delete db.sqlite3
  2. Delete all files in swirl/migrations/
  3. Run:
    python manage.py flush
    
  4. Repeat the migration process.

After flushing the database, don't forget to create a SWIRL Super User.

Configuring Django

SWIRL's Django configuration is managed in:
swirl_server/settings.py

Key Configuration Items

Hostname & Protocol

# Set the Fully Qualified Domain Name (FQDN) first
ALLOWED_HOSTS = ['localhost']
HOSTNAME = ALLOWED_HOSTS[0]
PROTOCOL = 'http'

The FQDN SWIRL should listen on must be the first entry in ALLOWED_HOSTS.

Time Zone

TIME_ZONE = 'US/Eastern'
CELERY_TIMEZONE = "US/Eastern"
CELERY_TIME_ZONE = "US/Eastern"

Celery Beats

Celery-Beats is used for scheduled services like the Search Expiration Service and the Search Subscription Service.

CELERY_BEAT_SCHEDULE = {
    # Executes every hour
    'expire': { 
         'task': 'expirer', 
         'schedule': crontab(minute=0, hour='*'),
    },          
}

Database Provider

DATABASES = {
    "default": {
        "ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
        "NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
        "USER": os.environ.get("SQL_USER", "user"),
        "PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
        "HOST": os.environ.get("SQL_HOST", "localhost"),
        "PORT": os.environ.get("SQL_PORT", "5432"),
    }
}

The following sections apply only to SWIRL Community Edition. For Enterprise Edition instructions view the AI Connect Guide.

Configuring PostgreSQL as the Database Backend

  1. Install PostgreSQL (if not already installed).
  2. Ensure pg_config is in your PATH and runs from the command line.
  3. Install the PostgreSQL driver:
pip install psycopg2
  1. If you are usingUncomment the PostgreSQL connector** in these files:

swirl/connectors/__init__.py

# Uncomment this line to enable PostgreSQL
# from swirl.connectors.postgresql import PostgreSQL

swirl/models.py

CONNECTOR_CHOICES = [
    ...
    # Uncomment the line below to enable PostgreSQL
    # ('PostgreSQL', 'PostgreSQL'),
    ...
]

For further setup, follow the Django Database Configuration Guide.

Configuring Celery & Redis

SWIRL uses Celery for executing metasearch requests asynchronously, with Redis as the backend.

Celery is configured in at least three locations. They must be consistent!

1. swirl_server/celery.py

app = Celery('swirl_server', 
             broker='redis://localhost:6379/0', 
             backend='redis://localhost:6379/0')

To verify the setup, run Celery from the command line:

> transport:   amqp://guest:**@localhost:6379//
- ** ---------- .> results:     rpc://

2. swirl_server/settings.py (Django Settings)

# Celery Configuration Options
CELERY_TIMEZONE = 'US/Eastern'
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60
CELERY_BEAT_SCHEDULE = {
    'expire': {
         'task': 'expirer',
         'schedule': crontab(minute=0, hour='*'),
    },
    'subscribe': {
         'task': 'subscriber',
         'schedule': crontab(minute=0, hour='*/4'),
    },
}
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'

3. Celery Broker Settings Ensure Redis is running and configured properly. Alternatively, use RabbitMQ by uncommenting:

# CELERY_BROKER_URL = 'amqp://guest:guest@localhost:6379//'
# CELERY_RESULT_BACKEND = 'rpc://'

Security

The Django Secret Key

Django's SECRET_KEY is a cryptographic salt used for security. If changed, active users will need to log in again.

To generate a new secret key:

python -c "import secrets; print(secrets.token_urlsafe())"

For more details: Django Secret Key Guide.

SWIRL User & Group Support

Django provides built-in authentication with User and Group objects. These can be managed via the Django Console or API.

User Management API

URL Explanation
/swirl/users/ List User objects & create new users
/swirl/users/id/ Retrieve, delete, or edit a User object

Group Management API

URL Explanation
/swirl/groups/ List Group objects & create new groups
/swirl/groups/id/ Retrieve, delete, or edit a Group object

Alternatively, use the Django Console: Django console user object

For additional details, see User Authentication in Django.