This vignette covers CS9 installation options and infrastructure requirements.
Start here: SQLite, with no server
CS9 reads its database settings from CS9_DBCONFIG_*
environment variables. Set the driver to SQLite and every
access level becomes a file on disk. There is no server to install, no
Docker container to start, no schema to create, and no database user to
authenticate as.
-
Install CS9:
install.packages("cs9") -
Put these six settings in your
.Renviron. GiveCS9_PATHa real directory: an empty value counts as missing andcheck_environment_setup()reports it as an error. -
Restart R, then check the configuration:
library(cs9) cs9::check_environment_setup(verbose = FALSE)$status #> [1] "ok" -
Open the database. Step 3 only validates the variables. It reads no file and creates no table, because CS9 builds its table objects lazily. Connecting is what proves SQLite works:
cs9::config$tables$config_log$connect() #> Creating table config_log con <- DBI::dbConnect(RSQLite::SQLite(), Sys.getenv("CS9_DBCONFIG_DB_CONFIG")) DBI::dbListTables(con) #> [1] "config_log" DBI::dbDisconnect(con)DBIandRSQLitearrive withcsdb, which CS9 depends on, so neither needs installing separately.
CS9_DBCONFIG_ACCESS is a /-separated list
of access levels, and it must include config: CS9 builds
its four configuration tables from that access level. Every access level
in the list needs its own CS9_DBCONFIG_DB_<ACCESS>
variable holding the path to its file, so the list above needs
CS9_DBCONFIG_DB_CONFIG and
CS9_DBCONFIG_DB_ANON. CS9 creates each file, and any
missing parent directory, on the first connection.
The driver string is matched case-insensitively, so
SQLite, sqlite and SQLITE all
select it.
What SQLite does not need
check_environment_setup() does not ask for
CS9_DBCONFIG_SERVER, CS9_DBCONFIG_PORT,
CS9_DBCONFIG_USER, CS9_DBCONFIG_PASSWORD or
any CS9_DBCONFIG_SCHEMA_* variable when the driver is
SQLite. SQLite is a file, and it has no schemas.
That is about validation, not about reading. CS9 reads every
CS9_DBCONFIG_* variable into its configuration list
whatever the driver is, because that list has one shape for every
backend. The SQLite connection then uses none of them. Setting
CS9_DBCONFIG_SERVER under SQLite is recorded and ignored,
not rejected.
vignette("backends", package = "cs9") puts the SQLite
and PostgreSQL environments side by side, and lists what each backend
does with every variable.
cs9example needs no .Renviron at all
cs9example is a
complete surveillance system you can run on a bare machine. It sets its
own SQLite configuration under tempdir() whenever
CS9_DBCONFIG_ACCESS is empty, so it needs no
.Renviron, no server and no configuration of any kind:
A real .Renviron still wins. The defaults apply only
when CS9_DBCONFIG_ACCESS is unset.
Installation options
CS9 can be used in two configurations.
CRAN installation (limited functionality)
Install CS9 from CRAN for documentation, examples, and development tools:
install.packages("cs9")
library(cs9)What works:
- Package documentation and help files
- Function examples and vignettes
- Environment diagnostics
(
cs9::check_environment_setup()) - Code templates and development utilities
- Basic configuration management
What does not work:
- Database connectivity
- Running surveillance tasks
Database setup
CS9 uses PostgreSQL as its production database backend. The rest of this section sets one up. If you want the SQLite backend instead, everything you need is at the top of this vignette and none of the steps below apply.
Database schema setup
Once PostgreSQL is running, create your surveillance database:
-- Connect as postgres user
CREATE DATABASE cs9_surveillance;
CREATE USER cs9_user WITH PASSWORD 'yourStrongPassword100';
GRANT ALL PRIVILEGES ON DATABASE cs9_surveillance TO cs9_user;
-- Create schemas for different access levels
\c cs9_surveillance
CREATE SCHEMA config;
CREATE SCHEMA anon;
GRANT ALL ON SCHEMA config TO cs9_user;
GRANT ALL ON SCHEMA anon TO cs9_user;Environment variable configuration
CS9 reads its database connection settings from environment
variables, which are typically set in your .Renviron
file.
Setting up .Renviron
-
Find or create your .Renviron file:
# Check current .Renviron location Sys.getenv("R_ENVIRON_USER") # Open .Renviron file for editing file.edit("~/.Renviron") Add CS9 configuration variables:
# CS9 Core Configuration
CS9_AUTO=0
CS9_PATH=/home/myuser/cs9
# Database Connection Settings
CS9_DBCONFIG_ACCESS=config/anon
CS9_DBCONFIG_DRIVER=PostgreSQL Unicode
CS9_DBCONFIG_PORT=5432
CS9_DBCONFIG_SERVER=localhost
CS9_DBCONFIG_USER=cs9_user
CS9_DBCONFIG_PASSWORD=yourStrongPassword100
CS9_DBCONFIG_SSLMODE=prefer
CS9_DBCONFIG_ROLE_CREATE_TABLE=x
# Database Schema Configuration
CS9_DBCONFIG_SCHEMA_CONFIG=config
CS9_DBCONFIG_DB_CONFIG=cs9_surveillance
CS9_DBCONFIG_SCHEMA_ANON=anon
CS9_DBCONFIG_DB_ANON=cs9_surveillanceCS9_PATH must be a real directory. An empty value counts
as missing, and check_environment_setup() reports it as an
error.
Set CS9_DBCONFIG_ROLE_CREATE_TABLE even when you want no
role, and use x for that. Leaving the variable out is not
the same as leaving it unset in R: Sys.getenv() returns
"", csdb substitutes the x
sentinel only for a NULL, and its PostgreSQL
create_table then emits SET ROLE "" in front
of the CREATE TABLE.
-
Restart your R session after editing
.Renviron.
Variable descriptions
| Variable | Example Value | Description |
|---|---|---|
CS9_AUTO |
0 |
Set to 0 for interactive mode, 1 for automated mode |
CS9_PATH |
/home/myuser/cs9 |
Base path for cs9::path function. Must be a real directory: an empty value counts as missing and fails validation |
CS9_DBCONFIG_ACCESS |
config/anon |
Database access levels (slash-separated) |
CS9_DBCONFIG_DRIVER |
PostgreSQL Unicode |
Database driver name |
CS9_DBCONFIG_SERVER |
localhost |
Database server hostname or IP |
CS9_DBCONFIG_PORT |
5432 |
Database server port |
CS9_DBCONFIG_USER |
cs9_user |
Database username |
CS9_DBCONFIG_PASSWORD |
yourStrongPassword100 |
Database password |
CS9_DBCONFIG_SSLMODE |
prefer |
SSL connection preference |
CS9_DBCONFIG_ROLE_CREATE_TABLE |
x |
Role to take when creating tables. x means take no
role |
CS9_DBCONFIG_SCHEMA_CONFIG |
config |
Schema for CS9 configuration tables |
CS9_DBCONFIG_DB_CONFIG |
cs9_surveillance |
Database for configuration |
CS9_DBCONFIG_SCHEMA_ANON |
anon |
Schema for anonymous data tables |
CS9_DBCONFIG_DB_ANON |
cs9_surveillance |
Database for surveillance data |
Package behavior without database configuration
When the database is not configured, CS9 loads with limited functionality and prints messages like:
Environment setup failed: Missing required environment variables: CS9_DBCONFIG_ACCESS, CS9_DBCONFIG_DRIVER, CS9_DBCONFIG_PORT, CS9_DBCONFIG_SERVER
CS9 database configuration not available. Package loaded with limited functionality.
Use cs9::check_environment_setup() to diagnose configuration issues.
Run cs9::check_environment_setup() to see which
configuration items are missing.
Docker
An example docker-compose file is available here.
To get started quickly, clone the cs9example repository, which provides a complete template for a CS9 surveillance system.
Apache Airflow Integration
For production surveillance systems, CS9 tasks are typically orchestrated by Apache Airflow. NorSySS uses Airflow to schedule overnight processing pipelines that sequence data retrieval, cleaning, analysis, and output generation — with each step verified before the next begins.
Airflow scheduling pattern
Each CS9 task maps to an Airflow task within a DAG (Directed Acyclic Graph). A typical surveillance DAG runs overnight:
Benefits of Airflow + CS9
- Dependency management: Airflow ensures cleaning completes before analysis begins
- Retry logic: Failed tasks retry automatically with configurable policies
- Monitoring: Web UI shows pipeline status, execution times, and failure history
- Scheduling: Cron-based scheduling for daily, weekly, or custom intervals
- Alerting: Notifications on pipeline failures via email, Slack, or other channels
Docker Compose with Airflow
For a complete Airflow + CS9 deployment, see the docker-examples-csids repository. A typical production setup includes:
- Airflow webserver + scheduler: Pipeline orchestration (port 8080)
- PostgreSQL: Database backend for both Airflow metadata and surveillance data
- CS9 worker: R environment with cs9 and surveillance packages installed
- Posit Workbench (optional): Interactive development environment (port 8786)
Moving from CRAN to full setup
If you installed CS9 from CRAN and want to enable full surveillance functionality:
-
Check your current status:
cs9::check_environment_setup() Install PostgreSQL, create the surveillance database, and note the connection parameters (host, port, username, password).
Add the
CS9_DBCONFIG_*variables to your.Renvironfile, restart R, and verify withcs9::check_environment_setup().-
Test that the package now loads fully:
ss <- cs9::SurveillanceSystem_v9$new(name = "test_system")
Verification and troubleshooting
Verify your setup
# Load CS9
library(cs9)
# Check environment configuration
cs9::check_environment_setup()
# Test surveillance system creation
ss <- cs9::SurveillanceSystem_v9$new(name = "test_surveillance")
print(ss$name) # Should print "test_surveillance"Common issues
“Missing required environment variables”: Check that
all CS9_DBCONFIG_* variables are in your
.Renviron file and restart R.
“Could not connect to database”: - Verify PostgreSQL
is running: sudo systemctl status postgresql (Linux) or
brew services list | grep postgres (macOS) - Confirm that
the credentials in .Renviron match the database user you
created - Test manually:
docker exec -it cs9-postgres psql -U cs9_user -d cs9_surveillance
“Package loaded with limited functionality”: Expected when no database is configured. Follow the database setup steps above.
Permission denied errors: Grant the required privileges:
Next steps
-
vignette("cs9")— architecture and core concepts -
vignette("creating-a-task")— step-by-step task tutorial -
vignette("file-layout")— package structure guidance - cs9example — a complete implementation template
