A modern, full-stack web interface for managing Selectel Container Registry (CRaaS) repositories and images.
- Project & Registry Management: Browse projects and registries within your Selectel account.
- Repository Insights: View repositories and their details.
- Image Management: List images with detailed metadata (tags, size, creation date).
- Bulk Cleanup: Select multiple images to delete at once.
- Garbage Collection Control: Option to trigger Garbage Collection (GC) immediately upon deletion.
- Destructive Action Guards:
- Confirmation modals for deleting registries and repositories require typing the resource name for verification.
- Single image deletion now supports the "Run GC" option via a unified confirmation dialog.
- Configuration Control: Environment-based feature flags to disable destructive actions (registry, repository, or image deletion).
- Optimistic UI Updates: Immediate feedback on deletion actions without waiting for full list re-fetching.
- Responsive UI: Built with Vue 3 and modern SCSS for a clean dark-mode experience, with responsive sidebar and tooltips for disabled actions.
- Backend: Go 1.24+ (Chi router, Selectel SDK, Slog logging).
- Frontend: Vue 3, TypeScript, Pinia (Setup Stores), Vite.
- Testing: Playwright for frontend verification.
- Linting: Oxlint and ESLint for frontend code quality.
- Go 1.24+
- Node.js 18+
- A Selectel account with API credentials.
The application is configured via environment variables. You can set these directly or use a .env file in the
backend/ directory.
To connect to the Selectel Container Registry, you need credentials for a user with access to your project. It is strongly recommended to create a dedicated Service User for this purpose.
- Log in to the Selectel Control Panel.
- Navigate to Identity & Access Management > User Management.
- Create a new Service User (or use an existing one).
- Note the User Name (
SELECTEL_USERNAME) and Password (SELECTEL_PASSWORD). - Note the Account ID (
SELECTEL_ACCOUNT_ID) from the top-right corner of the panel (numeric ID).
- Note the User Name (
- Ensure the user has access to the project containing your registries.
- Note the Project Name (
SELECTEL_PROJECT_NAME).
- Note the Project Name (
| Variable | Description | Default |
|---|---|---|
WEB_PORT |
Port for the backend server | 8080 |
SELECTEL_USERNAME |
Selectel Username | (Required) |
SELECTEL_ACCOUNT_ID |
Selectel Account ID | (Required) |
SELECTEL_PASSWORD |
Selectel Password | (Required) |
SELECTEL_PROJECT_NAME |
Selectel Project Name (Required) | (Required) |
SELECTEL_AUTH_URL |
Selectel Auth URL | https://cloud.api.selcloud.ru/identity/v3/auth/tokens |
SELECTEL_PROJ_URL |
Selectel Projects URL | https://cloud.api.selcloud.ru/identity/v3/auth/projects |
SELECTEL_CRAAS_URL |
Selectel CRaaS API Endpoint | https://cr.selcloud.ru/api/v1 |
CORS_ALLOWED_ORIGIN |
Allowed Origin for CORS requests | * |
You can protect the web interface with Basic Authentication to restrict access.
| Variable | Description | Default |
|---|---|---|
AUTH_ENABLED |
Enable Basic Auth for the web interface | false |
AUTH_LOGIN |
Username for web interface login | (Required if enabled) |
AUTH_PASSWORD |
Password for web interface login | (Required if enabled) |
JWT_SECRET |
Secret key for signing JWT tokens | (Auto-generated) |
COOKIE_SECURE |
Set the Secure flag on the auth cookie (requires HTTPS) |
true |
COOKIE_SAMESITE |
Set the SameSite attribute (lax, strict, none) |
lax |
Depending on how you deploy the frontend and backend, you may need to adjust the cookie settings so browsers don't reject the authentication token:
- Production (Same Domain, HTTPS):
COOKIE_SECURE=trueCOOKIE_SAMESITE=lax(orstrict)- Use case: Frontend at
https://craas.example.comand backend proxying/apion the same domain.
- Production (Cross-Domain/Subdomain, HTTPS):
COOKIE_SECURE=trueCOOKIE_SAMESITE=none- Use case: Frontend at
https://frontend.example.comand backend athttps://api.example.com.
- Local Development via Docker (Cross-Origin HTTP):
COOKIE_SECURE=falseCOOKIE_SAMESITE=none- Use case: Accessing the frontend via a local domain (e.g.,
http://frontend.local) while the backend runs onhttp://localhost:8080.
Control which operations are permitted and protect critical resources.
| Variable | Description | Default |
|---|---|---|
ENABLE_DELETE_REGISTRY |
Allow deletion of entire registries | false |
ENABLE_DELETE_REPOSITORY |
Allow deletion of repositories | false |
ENABLE_DELETE_IMAGE |
Allow deletion of images (single or bulk) | false |
ENABLE_MISSING_TAGS_CHECK |
Resolve and display tags not returned by listing | false |
PROTECTED_TAGS |
Comma-separated list of tags that cannot be deleted | (empty) |
| Variable | Description | Default |
|---|---|---|
LOG_LEVEL |
Logging level ( debug, info, warn, error) |
INFO |
LOG_FORMAT |
Log format (text, json) |
TEXT |
You can run backend and frontend separately for development.
-
Backend:
cd backend # Install dependencies go mod download # Run the server go run cmd/server/main.go
The server will start on port 8080 (or as configured). It supports graceful shutdown (Ctrl+C).
-
Frontend:
cd frontend # Install dependencies npm install # Start dev server npm run dev
The frontend will start on http://localhost:5173 and proxy
/apirequests tohttp://localhost:8080.
You can use the Makefile in the root directory:
make allTo run lint checks:
make lint-frontendTo run the built artifacts:
make run-backend
# In a separate terminal
make run-frontendThis repository includes a docker-compose.example.yml file to demonstrate how to deploy the application using Docker
Compose.
The frontend image supports runtime configuration for the backend API URL. This allows you to build the image once and deploy it to different environments without rebuilding.
Set the API_BASE_URL environment variable for the frontend container to point to your backend API.
Note: The API_BASE_URL must be accessible from the user's browser (e.g., https://api.example.com or http://localhost:8080 for local development). Do not use internal Docker network aliases (like http://backend:8080) as the frontend runs in the client's browser.
-
Copy the example file:
cp docker-compose.example.yml docker-compose.yml
-
Edit
docker-compose.ymlto set your Selectel credentials and preferred configuration. -
Run the stack:
docker-compose up -d
backend/: Go backend source code.cmd/server: Entry point.internal/auth: Selectel Keystone authentication.internal/config: Configuration loading and feature flags.internal/craas: CRaaS service integration (modularized services).internal/api: REST API handlers (split by domain: projects, registries, repositories, images).
frontend/: Vue frontend source code.src/api: Centralized Axios client.src/stores: Pinia stores for state management (Registry, Config).src/views: Vue components for pages.src/components: Reusable UI components (ConfirmModal, ToastNotification).src/types: Centralized TypeScript interfaces.
- Refactored Architecture: Backend handlers are now domain-specific, reducing code duplication via shared middleware for token management. Frontend uses a centralized API client and type definitions.
- Concurrency: Image tag verification uses
errgroupfor efficient parallel fetching. - User Safety: "Destructive Action Guards" require explicit confirmation (typing the resource name) for critical deletions.
- Optimized UX: Single image deletion now uses the bulk cleanup endpoint to allow optional Garbage Collection control, and UI updates are optimistic.