System Backup and Restore

To persist its data, CVEScan uses a PostgreSQL database for the API and Keycloak services, and a file system for static files such as vault logos. This section provides information on how to backup and restore the system, including the database and static files.

Database

CVEScan uses a single PostgreSQL server for both the API and Keycloak databases (same server, different databases). Within the database container, we have included two scripts, cvescan-backup and cvescan-restore, which are built on top of pg_dump and pg_restore to facilitate database backup and restoration. Nevertheless, if you feel more comfortable using the pg_dump and pg_restore commands directly (or any other tool), you can do so at your own risk.

Info

Static files such as vault logos are not saved in the database, and they are stored in the file system inside the API server container. Please refer to the static files section for more information on how to backup and restore static files.

To run the backup and restore scripts, you need to access the shell of the database container. You can do this by running the following command:

docker compose exec database bash

Generating Backup Files

Before you proceed

If feasible, temporarily stopping the services that are using the concerned database or halting incoming traffic to them is recommended before generating a backup file. While not strictly mandatory, this precaution reduces the risk of capturing intermediate or functionally incomplete data in the backup. This is particularly important because some services, especially those handling time-consuming operations or operations requiring interactions with external systems, may not use a single database transaction to ensure atomicity of a functional business operation. Instead, these services often rely on their own code based logic to manage rollbacks in case of failures. As a result, if a backup is taken during such an operation, there is a possibility of including data that has not yet been fully processed or rolled back. Halting the services or incoming traffic minimizes this risk, ensuring that the backup captures a consistent state of the database in term of business logic.

That said, it is important to emphasize that the likelihood of encountering such a scenario is extremely rare. Even in the rare event that it does occur, the backup file will always remain free of corruption in terms of database structure and content, ensuring that the database can still be restored without any issues. Furthermore, most services are designed to handle incomplete data gracefully, either by attempting to self-heal or by throwing errors that can be debugged and resolved by developers. This makes such situations not only uncommon but also manageable, ensuring the reliability and recoverability of the system.

To generate a backup file for the API or Keycloak database, you need to run the cvescan-backup script available inside the database container:

cvescan-backup <api|keycloak>

The backup file will be saved in the /var/backups inside the container. The provided docker-compose.yml file mounts the <repo_dir>/.backups/db folder on your host machine to /var/backups inside the container, so the backup file will also be saved in that folder on your host machine. If you changed the mount point in the docker-compose.yml file, you will find the backup file in the specified folder on your host machine.

  • Command to generate a backup file for the API database:

    cvescan-backup api
    
  • Command to generate a backup file for the Keycloak database:

    cvescan-backup keycloak
    

Please note

  • The backup process can take some time, depending on the size of the database.
  • Some operating systems or file systems may have restrictions on the maximum file size. If the backup file exceeds this limit, it may not be created successfully.

Restoring a Database

To restore the API or Keycloak database, follow these steps:

  1. Make sure the backup file is available inside the container:

    If you have the <repo_dir>/.backups/db folder on your host machine mounted to /var/backups inside the container, you can copy the backup file to that folder on your host machine, and it will be immediately available inside the container.

    Please note:

    • Only .dump files are supported by the restore script.
    • The <repo_dir>/.backups/db folder on your host machine will probably have restricted access rights, so you may need to use the root user to copy the file.
    • You can also use docker compose cp or docker cp to copy the file from your host machine to the container:

      docker cp <backup_file_path> <container_id>:/var/backups
      

      or:

      docker compose cp <backup_file_path> database:/var/backups
      
  2. Ensure the target database does not exist:

    Important

    • Dropping the database will result in the loss of all existing data. Make sure to have a backup file and to store it securely before proceeding. It is strongly advised to keep a copy of the backup file outside the container to prevent its loss in case the container is removed or the volume is deleted or not configured properly.
    • If you have a service that is using the database, you may need to stop that service before dropping the database to avoid any conflicts.

    To drop a database, you can use the following command inside the database container:

    dropdb -U <database_user> <database_name>
    

    Example command to drop a database named cvescan_api_db using the api_db_user user:

    dropdb -U api_db_user cvescan_api_db
    
  3. Run the restore script available inside the container:

    To restore a database, you need to run the cvescan-restore script available inside the database container:

    cvescan-restore <api|keycloak> <backup_file_path>
    

    The restore script will automatically create the database with the correct name and owner and restore the data from the backup file.

    Example command to restore the API database from a backup file named backup.dump stored in the /var/backups folder inside the container:

    cvescan-restore api /var/backups/backup.dump
    
  4. Restart the services:

    After restoring a database, you need to restart the services that are connected to that database. You can do this by running the following command from the host machine:

    docker compose restart <service_name>
    

Troubleshooting

  • Database already exists: If you encounter an error stating that the database already exists, make sure to drop the existing database before restoring the backup.
  • File not found: Verify that the backup file is accessible inside the container at the specified path.
  • Permission denied when copying the backup file to mounted directory: If you encounter a permission denied error when copying the backup file, you may need to change the permissions on the mounted folder on your host machine or use the root user to copy the file.
  • Keycloak attempting to join a cluster after a successful database restore: If you are using the same configuration as the provided docker-compose.yml file, this issue will not occur because the Keycloak container is configured to use only the local cache. However, it may arise if the backup file contains a keycloak database that was previously used in a clustered environment.

    It is worth noting that when Keycloak tries to join a cluster, it will fail multiple times before automatically switching to standalone mode. This behavior is not problematic because the Keycloak container is isolated from any external network, eliminating the possibility of it joining an actual cluster. Additionally, the data in the restored database is sufficient for Keycloak to operate seamlessly in standalone mode. While users will need to re-log into the WebUI after the restore, this is a minor inconvenience and does not affect the functionality of the system.

Static Files

Static files such as vault logos are stored in the file system inside the API server container. You can find the storage folder at /app/.storage inside the API container. If you want to backup or restore the storage folder, you can follow one of the methods below.

Method 1: Direct Folder Copy

Backup

You can backup the storage folder inside the API server container by copying it directly to your host machine. Use the following command to copy the storage folder from the API server container to your host machine:

docker compose cp api:/app/.storage <host_folder_path>

Restore

To restore the storage folder from your host machine to the API server container, use the following command:

docker compose cp <host_folder_path> api:/app

Note: Make sure the storage folder on your host machine is named .storage before copying it to the container.

Method 2: Compress and Copy

Backup

If you want to compress the storage folder before copying it, you can use the following commands:

  1. Compress the storage folder inside the container:

    docker compose exec api tar -czf /tmp/storage.tar.gz -C /app .storage
    
  2. Copy the compressed file to your host machine:

    docker compose cp api:/tmp/storage.tar.gz <host_folder_path>
    
  3. Remove the compressed file from the container:

    docker compose exec api rm /tmp/storage.tar.gz
    

Restore

If you have a compressed file, you can use the following commands to restore the storage folder:

  1. Copy the compressed file to the container:

    docker compose cp <host_folder_path>/storage.tar.gz api:/tmp/storage.tar.gz
    
  2. Extract the compressed file inside the container:

    docker compose exec api tar -xzf /tmp/storage.tar.gz -C /app
    
  3. Remove the compressed file from the container:

    docker compose exec api rm /tmp/storage.tar.gz