Jump to content
Jump to navigation

Jump to heading The command line interface

The CLI provides a thin wrapper to access the REST API of Scotty. It is written in Rust and provides a simple interface to list, create, update and destroy apps, as well as manage authorization (scopes, roles, assignments).

You can get help by running scottyctl --help and scottyctl --help <command>.

Jump to heading Authentication

Scotty supports two authentication methods:

Jump to heading OAuth Authentication (Recommended)

Use the device flow to authenticate interactively:

scottyctl --server https://scotty.example.com auth:login

This command will:

  1. Open your browser to authenticate with the OIDC provider
  2. Store the OAuth token securely for future commands
  3. Automatically refresh tokens when they expire

Managing OAuth sessions:

# Check authentication status
scottyctl auth:status

# Refresh the token
scottyctl auth:refresh

# Logout and clear stored credentials
scottyctl auth:logout

Jump to heading Bearer Token Authentication

For service accounts, CI/CD, or when OAuth is not available, use bearer tokens:

# Via command line argument
scottyctl --server https://scotty.example.com --access-token <TOKEN> app:list

# Via environment variable (recommended)
export SCOTTY_SERVER=https://scotty.example.com
export SCOTTY_ACCESS_TOKEN=<TOKEN>
scottyctl app:list

Note: For the rest of this documentation, command examples use --server and --access-token for clarity, but you can always use OAuth via auth:login or environment variables instead.

Jump to heading List all apps

scottyctl --server <SERVER> --access-token <TOKEN> app:list

Example output: Example output of app:list

The table contains all apps with their status, uptime and URLs. The URLs are the public URLs of the apps. The status can be one of the following:

  • Running: The app is running
  • Stopped: The app is stopped
  • Unsupported: The app is not supported by the server

Jump to heading Get info about an app

scottyctl --server <SERVER> --access-token <TOKEN> app:info <APP>

Example output: Example output of app:info

The command lists all services of a specific app and their status. The output also contains the enabled notification services for that app.

Jump to heading View logs from an app service

scottyctl --server <SERVER> --access-token <TOKEN> app:logs <APP> <SERVICE>

This command displays logs from a specific service within an app. By default, it shows all available logs and exits.

Jump to heading Options

  • -f, --follow: Follow log output in real-time (like tail -f)
  • -n, --lines <LINES>: Show only the last N lines
  • --since <SINCE>: Show logs since a timestamp (e.g., "2h", "30m", "2023-01-01T10:00:00Z")
  • --until <UNTIL>: Show logs until a timestamp (e.g., "1h", "2023-01-01T11:00:00Z")
  • -t, --timestamps: Include timestamps in the log output

Jump to heading Examples

View all logs:

scottyctl app:logs my-app web

Follow logs in real-time:

scottyctl app:logs my-app web --follow

Show last 100 lines with timestamps:

scottyctl app:logs my-app web --lines 100 --timestamps

Show logs from the last 2 hours:

scottyctl app:logs my-app web --since 2h --follow

Jump to heading Open an interactive shell in an app service

scottyctl --server <SERVER> --access-token <TOKEN> app:shell <APP> <SERVICE>

This command opens an interactive shell session inside a running container. This is useful for debugging, inspecting files, or running commands inside the container environment.

Note: The shell command requires the shell permission in the authorization system.

Jump to heading Options

  • -c, --command <COMMAND>: Execute a single command instead of opening an interactive shell. The command will run and scottyctl will exit with the same exit code as the command.
  • --shell <SHELL>: Specify which shell to use (default: /bin/bash)

Jump to heading Examples

Open an interactive shell:

scottyctl app:shell my-app web

Execute a single command:

scottyctl app:shell my-app web --command "ls -la /app"

Use a different shell:

scottyctl app:shell my-app web --shell /bin/sh

Change to a specific directory and run commands:

scottyctl app:shell my-app web --command "cd /var/www && pwd && ls -la"

Run a script and capture its exit code:

scottyctl app:shell my-app web --command "/app/scripts/healthcheck.sh"
echo "Exit code: $?"

Jump to heading Start/run an app

scottyctl --server <SERVER> --access-token <TOKEN> app:start <APP>
scottyctl --server <SERVER> --access-token <TOKEN> app:run <APP>

The command will start an app and print the output of the start process. After the command succeeds, it will print the app info.

Jump to heading Stop an app

scottyctl --server <SERVER> --access-token <TOKEN> app:stop <APP>

The command will stop an app and print the output of the stop process. After the command succeeds, it will print the app info.

Jump to heading Rebuild an app

scottyctl --server <SERVER> --access-token <TOKEN> app:rebuild <APP>

The command will rebuild an app and print the output of the rebuild process. Part of the rebuild process is rewriting the proxy configuration, pulling new images for the app and rebuilding local images if necessary. The app itself will also be powered off and on again.

Jump to heading Purge an app

scottyctl --server <SERVER> --access-token <TOKEN> app:purge <APP>

The command will purge all temporary data of an app, especially logs, temporary docker containers and other ephemeral data. It will not delete any persistent data like volumes or databases. If the app was running, it will be stopped by this command.

Jump to heading Create an app

scottyctl --server <SERVER> --access-token <TOKEN> app:create <APP> --folder <FOLDER> \
  --service <SERVICE:PORT> [--service <SERVICE:PORT> ...] \
  [--app-blueprint <BLUEPRINT>] [--ttl <LIFETIME>] \
  [--basic-auth <USERNAME:PASSWORD>] [--allow-robots] \
  [--destroy-on-ttl] \
  [--custom-domain <DOMAIN:SERVICE>] [--custom-domain <DOMAIN:SERVICE> ...] \
  [--env <KEY=VALUE>] [--env <KEY=VALUE> ...] \
  [--env-file <FILE>] \
  [--registry <REGISTRY>] \
  [--middleware <MIDDLEWARE>] [--middleware <MIDDLEWARE> ...]

This command will create a new app on the server. The --folder argument is mandatory and should point to a folder containing at least a compose.yml file. The complete folder will be uploaded to the server (size limits may apply).

Jump to heading Controlling File Uploads with .scottyignore

You can control which files are uploaded by creating a .scottyignore file in your project folder. This file uses gitignore-style patterns to exclude files from being uploaded.

Pattern Examples:

# Ignore log files
*.log

# Ignore build artifacts
target/
node_modules/
dist/

# Ignore environment files
.env
.env.local

# Re-include specific files using ! (negation)
!important.log

# Ignore files in any subdirectory
**/*.tmp
**/.cache/

Common patterns:

Pattern Description
*.log Ignore all .log files in any directory
target Ignore the target directory and all its contents
!important.log Re-include important.log even if *.log is ignored
**/*.tmp Ignore .tmp files in any subdirectory
.env* Ignore .env, .env.local, etc.
# comment Comments (ignored)

Note: The following files are always ignored automatically:

  • .DS_Store (macOS system file)
  • .git/ directory and its contents

You either need to declare a public service via --service or use the --app-blueprint argument (You can get a list of available blueprints with scottyctl blueprint:list). When declaring a public service, you need to provide a service name and a port. The service name should match a service in the compose.yml file. The port should be the port the service is listening on.

The --ttl argument is optional and will set the lifetime of the app in hours, days or forever.

You can add basic auth to the app with the --basic-auth argument. The argument should contain a username and a password separated by a colon.

The --allow-robots argument will inject a X-Robots-Tag: noindex header into all responses of the app. This will prevent search engines from indexing the app. (Not supported by all proxies)

The --destroy-on-ttl argument will destroy the app after the specified ttl instead of just stopping it. Suitable for apps that are not expected to be used for a long time. Tbhe --env-file argument will load environment variables from a file. The file should contain key-value pairs separated by an equal sign.

You can add custom domains to the app with the --custom-domain argument. The argument should contain a domain and a service name separated by a colon. The service name should match a service in the compose.yml file.

The --env-file argument will load environment variables from a file. The file should contain key-value pairs separated by an equal sign.

You can add environment variables to the app with the --env argument. The argument should contain a key and a value separated by an equal sign. You can reference secrets from 1Password with the OP-uri-scheme. The value should be a URL like op://<connect-instance-name>/<vault-uuid>/<item-uuid>/<field-name>. The server needs to be configured accordingly.

You can use a private registry for the images with the --registry argument. The argument should contain the name of the registry. The server needs to be configured accordingly.

You can add middleware to the app with the --middleware argument. The argument should contain the name of the middleware. Middleware must be in the allow-list in the server configuration before they can be used. You can specify multiple middleware by using the --middleware argument multiple times. (This is only supported for traefik)

Jump to heading Some examples:

scottyctl --server <SERVER> --access-token <TOKEN> app:create my-nginx-test \
  --folder . \
  --service nginx:80

will beam up the current folder to the server and start the nginx service on port 80.

scottyctl --server <SERVER> --access-token <TOKEN> app:create my-nginx-test \
  --folder . \
  --service nginx:80 \
  --basic-auth user:password \
  --allow-robots \
  --ttl forever

will beam up the current folder to the server and start the nginx service on port 80. It will add basic auth with the username user and the password password and won't add a X-Robots-Tag header to all responses. The app will run forever.

scottyctl --server <SERVER> --access-token <TOKEN> app:create my-nginx-test \
  --folder . \
  --service nginx:80 \
  --custom-domain nginx.example.com:nginx

will beam up the current folder to the server and start the nginx service on port 80. The app will be reachable under http://nginx.example.com.

Jump to heading Adopt an app

scottyctl --server <SERVER> --access-token <TOKEN> app:adopt <APP>

This command will adopt an unsupported app. For this to work, the app needs to be already in the server's app directory. The command will create a .scotty.yml file in the app directory and add the app to the server's database.

Scotty will also try to reuse the existing config from the load balancer and add that information to the .scotty.yml file. It will also dump all found environment variables into the .scotty.yml file.

After adopting an app, it is strongly advised to check the .scotty.yml file and remove any unnecessary information from it and double-check the configuration.

Jump to heading Destroy an app

scottyctl --server <SERVER> --access-token <TOKEN> app:destroy <APP>

This command will destroy only a supported app. It will stop the app, remove all ephemeral and persistent data and remove the app from the Scotty server. It will also delete the used images if they are not used somewhere else.

Caution: This command is irreversible! You might lose data if you run this command.

Jump to heading List all blueprints

scottyctl --server <SERVER> --access-token <TOKEN> blueprint:list

This will list all available blueprints on the server.

Jump to heading Get blueprint details

scottyctl --server <SERVER> --access-token <TOKEN> blueprint:info <BLUEPRINT>

This command displays detailed information about a specific blueprint, including its configuration, services, and required parameters.

Jump to heading Run a custom action

scottyctl --server <SERVER> --access-token <TOKEN> app:action <APP> <ACTION>

Execute a custom action defined in the app's .scotty.yml file. Custom actions allow you to run predefined commands or scripts within your application containers.

Example:

# Run a database migration action
scottyctl app:action my-app db:migrate

# Clear application cache
scottyctl app:action my-app cache:clear

Jump to heading Add a notification service to an app

scottyctl --server <SERVER> --access-token <TOKEN> notify:add <APP> \
  --service-id <SERVICE_TYPE://SERVICE_ID/CHANNEL|PROJECT_ID/MR_ID>

This command will add a notification service to an app. That means scotty will send a notification for every action on that app to the selected service. The service needs to be configured on the server.

Currently there are three service types available:

  • mattermost://SERVICE_ID/CHANNEL: Send a message to a mattermost channel
  • gitlab://SERVICE_ID/PROJECT_ID/MR_ID: Add a comment to a gitlab merge request
  • webhook://SERVICE_ID: Send a webhook to a configured URL

Jump to heading Remove a notification service from an app

scottyctl --server <SERVER> --access-token <TOKEN> notify:remove <APP> \
  --service-id <SERVICE_TYPE://SERVICE_ID/CHANNEL|PROJECT_ID/MR_ID>

This command will remove a notification service from an app. The format of SERVICE_ID is the same as in the notify:add command.

Jump to heading List all notification services of an app

scottyctl --server <SERVER> --access-token <TOKEN> app:info <APP>

For more info, see the help for app:info.

Jump to heading Authorization Management (Admin Commands)

These commands require admin_read or admin_write permissions. See the Authorization documentation for more details.

Jump to heading Scopes Management

List all scopes:

scottyctl --server <SERVER> --access-token <TOKEN> admin:scopes:list

Lists all authorization scopes with their descriptions and creation timestamps.

Create a new scope:

scottyctl --server <SERVER> --access-token <TOKEN> admin:scopes:create <NAME> <DESCRIPTION>

Example:

scottyctl admin:scopes:create staging "Staging environment applications"

Jump to heading Roles Management

List all roles:

scottyctl --server <SERVER> --access-token <TOKEN> admin:roles:list

Lists all roles with their descriptions and associated permissions.

Create a new role:

scottyctl --server <SERVER> --access-token <TOKEN> admin:roles:create <NAME> <DESCRIPTION> <PERMISSIONS>

Permissions should be comma-separated. Use * for all permissions.

Example:

# Create a developer role with specific permissions
scottyctl admin:roles:create developer "Developer access" view,manage,shell,logs,create

# Create an admin role with all permissions
scottyctl admin:roles:create admin "Full access" "*"

Jump to heading Assignments Management

List all user assignments:

scottyctl --server <SERVER> --access-token <TOKEN> admin:assignments:list

Lists all user-to-role assignments with their assigned scopes.

Create a new assignment:

scottyctl --server <SERVER> --access-token <TOKEN> admin:assignments:create <USER> <ROLE> <SCOPES>

Scopes should be comma-separated. Use * for all scopes.

Examples:

# Assign user to developer role in staging scope
scottyctl admin:assignments:create alice@example.com developer staging

# Assign bearer token to admin role across all scopes
scottyctl admin:assignments:create identifier:ci-bot admin "*"

# Assign user to multiple scopes
scottyctl admin:assignments:create bob@example.com operator staging,production

Remove an assignment:

scottyctl --server <SERVER> --access-token <TOKEN> admin:assignments:remove <USER> <ROLE> <SCOPES>

Example:

scottyctl admin:assignments:remove alice@example.com developer staging

Jump to heading Permissions Management

List all available permissions:

scottyctl --server <SERVER> --access-token <TOKEN> admin:permissions:list

Lists all permissions that can be assigned to roles.

Test permission for a user:

scottyctl --server <SERVER> --access-token <TOKEN> admin:permissions:test <USER> <APP> <PERMISSION>

Tests whether a specific user has a particular permission on an app.

Example:

scottyctl admin:permissions:test alice@example.com my-app manage

Get all permissions for a user:

scottyctl --server <SERVER> --access-token <TOKEN> admin:permissions:user <USER>

Displays all effective permissions for a user across all scopes.

Example:

scottyctl admin:permissions:user alice@example.com

Jump to heading Shell Completion

Generate shell completion scripts for bash, zsh, fish, or PowerShell:

scottyctl completion <SHELL>

Examples:

# Bash
scottyctl completion bash > /etc/bash_completion.d/scottyctl

# Zsh
scottyctl completion zsh > ~/.zsh/completion/_scottyctl

# Fish
scottyctl completion fish > ~/.config/fish/completions/scottyctl.fish

# PowerShell
scottyctl completion powershell > scottyctl.ps1

After installing the completion script, restart your shell or source the completion file.

Jump to heading Web UI: Viewing Logs

In addition to the CLI, Scotty provides a web interface for viewing container logs in real-time.

Jump to heading Accessing Service Logs

  1. Navigate to the Dashboard at /dashboard

Dashboard showing list of apps

  1. Click on an application to view its details

App detail page showing services

  1. In the Available Services section, click on a service name (e.g., "nginx", "web")
  2. The service detail page displays live-streaming logs

Log viewer showing real-time container logs

Jump to heading Log Viewer Features

The web-based log viewer provides:

  • Real-time streaming: Logs are streamed via WebSocket as they are generated
  • Line numbers: Each log line is numbered for easy reference
  • Auto-scroll: New log entries automatically scroll into view (can be toggled)
  • Timestamps: Option to show/hide timestamps in log output
  • Line count: Shows total number of log lines received
  • Streaming indicator: Shows when actively streaming new logs
  • Service information: The page shows service status, start time, and domain information

Jump to heading Permission Requirements

To view logs in the web UI, you need the logs permission for the application's scope. If you don't have this permission, you'll be redirected to the application detail page.

See the Authorization documentation for details on configuring permissions.

Jump to heading Security Best Practices

Jump to heading Shell Access Security

The app:shell command provides direct access to running containers. Consider these security practices:

Permission Management:

  • Grant shell permission only to users who require debugging access
  • Use scope-based authorization to limit shell access to specific environments (e.g., staging only, not production)
  • Regularly audit which users have shell access

Operational Security:

  • Shell sessions run as the container's default user (often root)
  • Commands executed via shell are not logged by Scotty—consider container-level audit logging if needed
  • Shell access bypasses application-level authentication

Container Isolation:

  • Shell sessions are isolated to the specific container
  • Users cannot access other containers or the host system directly
  • Network access from within the container follows the container's network configuration

Jump to heading Logs Access Security

Permission Management:

  • The logs permission grants access to all log output from a service
  • Logs may contain sensitive information (API keys, user data, error details)
  • Consider the sensitivity of log content when granting access

Data Considerations:

  • Log streaming is real-time only—historical logs depend on Docker's log retention
  • Logs are transmitted over WebSocket connections (encrypted if using HTTPS)

Jump to heading Troubleshooting

Jump to heading Common Issues

Jump to heading WebSocket Connection Failures

Symptoms: Logs not streaming, shell not connecting, "WebSocket error" messages

Solutions:

  1. Verify the Scotty server is running and accessible
  2. Check that your network allows WebSocket connections (some proxies block them)
  3. Ensure you're using the correct protocol (wss:// for HTTPS, ws:// for HTTP)
  4. Check browser console for specific error messages
# Test basic connectivity
curl -v https://your-scotty-server/api/health

Jump to heading Permission Denied Errors

Symptoms: "Permission denied" or "Forbidden" when accessing logs or shell

Solutions:

  1. Verify your authentication is valid:
    scottyctl auth:status
  2. Check your assigned permissions:
    scottyctl admin:permissions:user your@email.com
  3. Ensure you have the correct permission (logs or shell) for the app's scope
  4. Contact your administrator to request the necessary permissions

Jump to heading Log Stream Not Starting

Symptoms: Log viewer shows loading state but no logs appear

Solutions:

  1. Verify the service is running:
    scottyctl app:info <APP>
  2. Check that the container is producing logs:
    scottyctl app:logs <APP> <SERVICE> --lines 10
  3. Ensure you have the logs permission for the application
  4. Try refreshing the page to re-establish the WebSocket connection

Jump to heading Shell Session Issues

Symptoms: Shell connects but commands don't work, or session terminates unexpectedly

Solutions:

  1. Verify the container has the required shell:
    # Try a different shell if /bin/bash is not available
    scottyctl app:shell <APP> <SERVICE> --shell /bin/sh
  2. Check if the container is healthy and running:
    scottyctl app:info <APP>
  3. For Alpine-based images, use /bin/sh instead of /bin/bash
  4. If the session terminates, check container logs for crash information

Jump to heading Shell Exit Codes

When using --command, the exit code is passed through:

# Check if a file exists (exit 0 = exists, exit 1 = not found)
scottyctl app:shell my-app web --command "test -f /app/config.yml"
echo $status  # Fish shell
echo $?       # Bash/Zsh

Jump to heading Getting Help

If you encounter issues not covered here:

  1. Check the server logs for error details
  2. Enable debug logging: RUST_LOG=debug scottyctl ...
  3. Verify your scottyctl version matches the server version
  4. Report issues at the project repository