Migration checklist

Before starting your migration, check if your project meets these requirements:

✅ Supported Service Types

⚠️ Other Considerations

  • External resources can still be used by connecting to them
  • Database migrations need to be handled separately
  • Check that your project:
    • Is compatible with the latest Rust version
    • Can be built and run in a Docker container
If you’re unsure about any compatibility requirements, join our Discord community for help!

Migration Steps

Remember to install the Cyndra CLI if you haven’t yet!

1. Add Cyndra Dependencies

Add the required Cyndra dependencies to your Cargo.toml:

# Add the Cyndra runtime
cargo add cyndra-runtime

# Add your framework integration if supported (e.g., for Axum)
cargo add cyndra-axum

# Add any Cyndra resources you need (e.g., Postgres)
cargo add cyndra-shared-db --features postgres,sqlx

2. Update Your Main Function

Common steps needed for migrating are:

  • Change the main function to use #[cyndra_runtime::main].
  • Change the return type and return the framework’s Router or config. This varies by framework, check examples for more.
  • Add a Secrets.toml file and use #[cyndra_runtime::Secrets] instead of loading environment variables.
  • Use #[cyndra_shared_db::Postgres] instead of manually connecting to a database.

Here is an example of what an Axum service might look like before and after migrating:

main.rs (before)
#[tokio::main]
async fn main() {
    dotenvy::dotenv().ok();

    let db_url = std::env::var("DATABASE_URL").unwrap();
    let secret = std::env::var("MY_SECRET").unwrap();

    let pool = sqlx::Pool::connect(&db_url).await.unwrap();
    sqlx::migrate!().run(&pool).await.unwrap();

    // Use secrets for anything that needs them

    let router = create_api_router(pool);
    let addr = SocketAddr::from(([0, 0, 0, 0], 8000));

    Server::bind(&addr)
        .serve(router.into_make_service())
        .await
        .unwrap()
}
main.rs (after)
#[cyndra_runtime::main]
async fn main(
    #[cyndra_shared_db::Postgres] pool: PgPool,
    #[cyndra_runtime::Secrets] secrets: cyndra_runtime::SecretStore,
) -> cyndra_axum::CyndraAxum {
    sqlx::migrate!().run(&pool).await.unwrap();

    // Use secrets for anything that needs them

    let router = create_api_router(pool);

    Ok(router.into())
}

3. Add Cyndra configuration

If your app uses gitignored files, or uses static files at runtime, you need to add a Cyndra.toml file with some file declarations. Read more in Deployment files.

4. Testing it locally

cyndra run

5. Deploy

If everything is ready to launch:

cyndra deploy
The first deployment might take a few minutes as it sets up your infrastructure.

Next Steps