Label Studio (label-studio)
Data labeling of text, images, audio, video and time series, human review of model outputs, comparison of two answers (preferences) and preparation of the datasets used to fine-tune and evaluate the language and vision models (LLM and VLM: SFT, DPO). Projects, users and annotations live in the PostgreSQL database of the platform, uploaded media in an S3 bucket (SeaweedFS of the platform by default).
Generated from catalog/services/label-studio.yaml: do not edit by hand.
Summary
| Version | 1.23.2 |
| Use | install and configure, configure and connect |
| Layer | functional (AI catalog) |
| Category | Data platforms |
| Installation methods | podman |
| External connection | no |
| Sandbox only | no |
Licence
| SPDX identifier | Apache-2.0 |
| Licence policy | core licence (MIT or Apache-2.0) |
| Licence exception | - |
| Licence note | Label Studio Community Edition only: the Label Studio Enterprise and Starter Cloud editions of HumanSignal (roles, workspaces, SSO, review workflows) are commercial and are neither installed nor configured. |
| Platform component | label-studio |
Packages and artifacts
A package the project of the service publishes (its image, its binary archive, its Python or OS package) carries the licence of the service; a third-party package carries the licence written on its row, read from the official upstream metadata.
| Kind | Package | Version | Licence | Details |
|---|---|---|---|---|
| container image | docker.io/heartexlabs/label-studio | 1.23.2 | Apache-2.0 | image key label-studio, used by app, nginx, digest sha256:afcc516a22775a39d0d66f4c2ddc95d01be3e3d3862b21fcf4f9de34b4ad4e12 |
Images are pinned by tag in the descriptor, and by digest when the descriptor declares one (the offline bundle then refuses a pulled image that does not carry it); the digest is recorded in the mirror of the Manager when the offline bundle is imported, and every pull or load is checked against it.
Supported systems and architectures
| Method | Operating systems | Architectures |
|---|---|---|
podman | RHEL family (dnf), Debian family (apt), Arch Linux (pacman) | x86_64, aarch64 (not restricted by the descriptor) |
Certified host systems: RHEL 8/9/10, Rocky Linux 8/9/10, AlmaLinux 8/9/10, Oracle Linux 8/9, CentOS Stream 9/10, Ubuntu 22.04/24.04, Debian 12, Arch Linux (rolling). The host preflight accepts these systems (other releases of a known family give a warning, end of life releases are refused) and the x86_64 and aarch64 architectures.
Prerequisites
Host
- at least 4096 MB of memory (warning,
memory). - the program
podmaninstalled on the host (blocking,podman).
Programs the commands and checks of the service start on the host, outside the managed roots: add them to allowed_commands of the agent (see Security of the Navin agent), else the agent refuses them with command_not_allowed: /usr/bin/curl.
Network and ports
| Component | Port name | Port | Opened in the host firewall |
|---|---|---|---|
app | app | 8091/tcp (mode standalone) | no |
app | app | 8091/tcp (mode replicated) | yes |
nginx | web | 8090/tcp | yes |
Services and connections needed
database:postgresql.s3:seaweedfs.
Details and resolution: see Dependencies.
Installation methods and modes
| Method | Default | What the method uses |
|---|---|---|
podman | yes | the container images of the descriptor, run by Podman under systemd |
Components
| Component | Kind | Installation methods | Ports |
|---|---|---|---|
Application (app) | master | podman | 8091/tcp (mode standalone), 8091/tcp (mode replicated) |
Interface (nginx) | master | podman | 8090/tcp |
nginxruns only on a host that also runsapp(modestandalone).
Single server (standalone) (default)
One application and one interface on the same host, joined on the network of the service.
What the mode deploys:
| Component | Placement |
|---|---|
app | min 1, max 1 |
nginx | min 1, max 1 |
Replicated (replicated)
Several stateless applications sharing the database, the S3 bucket and the secret key; each interface balances over every application and the load balancer spreads the users over the interfaces.
What the mode deploys:
| Component | Placement |
|---|---|
app | min 2, recommended 2 |
nginx | min 1, recommended 2 |
Install this service
The install wizard of the Navin Manager plans, validates and runs the installation; you need the services:install permission on the cluster.
-
Open the wizard. In Clusters, choose the row action Install services of the target cluster. The wizard opens on its first step, Service.
-
Choose the service. On the Service step, select Label Studio. The card shows the licence
Apache-2.0and the dependencies the installation needs. -
Choose the hosts and the mode. On the Hosts step, tick the hosts, then choose the Mode:
standalone(default),replicated. Each mode deploys the components listed in Installation methods and modes. With several components, place each one on its hosts in Component placement (Suggest placement proposes a placement that respects the cardinalities). -
Bind the dependencies. On the Bindings step, choose for each dependency (
database,s3) Install with the platform or Use an existing connection; an optional dependency can stay on No binding. -
Configure. On the Configure step, review the parameters (see Configuration parameters). Passwords left empty with a generated default are generated and sealed by the Manager.
-
Review and install. On the Install step the Manager validates the plan and shows the installation order; when it says "The plan is valid. Ready to install.", choose Install. A highly available mode is installed only when its HA checks pass.
-
Verify. The operation ends when the health checks of every instance pass (see Health checks); the service then shows as running in Services.
Connect an existing service
| Schemes | https, http |
| Default port | 8080 |
| Authentication | required |
| Health check | /health/ |
| Authentication method | Fields | Description |
|---|---|---|
personal_access_token | password | Personal access token of a Label Studio user (Account & Settings), entered as the password: the Manager exchanges it at /api/token/refresh/ for a short access token sent as Authorization: Bearer. |
legacy_token | api_key | Legacy token of a user, sent as Authorization: Token; the legacy tokens must be enabled for the organization (Organization, Settings, Access Token Settings). |
Official documentation: https://labelstud.io/guide/access_tokens
High availability
| Cluster | replicas (replication) |
| High availability | external (external) |
| Failover | load balancer (load-balancer) |
| Replication | shared store (shared-store) |
| Quorum | none (none) |
| Discovery | none (none) |
| Entry point | load balancer (load-balancer) |
| Official documentation | https://labelstud.io/guide/persistent_storage |
| References | https://labelstud.io/guide/storedata, https://labelstud.io/guide/install_k8s, https://labelstud.io/guide/security |
Prerequisites
| Prerequisite | Must be highly available | Modes | Description |
|---|---|---|---|
database | yes | modes of level ha or cluster | Highly available PostgreSQL holding the projects, the annotations and the users. |
s3 | yes | modes of level ha or cluster | Highly available S3 storage (SeaweedFS in distributed mode) shared by every application. |
Topology per mode
| Modes | Highest catalog level | Distribution | Quorum component | Fault domains | Description |
|---|---|---|---|---|---|
standalone | standalone (standalone) | single (single) | - | 1 | One application and one interface, no fault tolerance. |
replicated | ha (ha) | active-active (active-active) | - | 2 | Stateless applications and interfaces on distinct hosts behind the load balancer (HAProxy and keepalived). |
Notes
- Every replica shares the secret key of the installation (the sessions are signed cookies), the database and the S3 bucket: any replica serves any user. The migrations of a new version run at the start of each application under a database lock (locked_migrate), so the replicas can start together.
- The Community Edition has no roles: every member of the organization sees every project. Access is controlled by the invitation link, the sign up setting and the authenticating gateway of the platform.
Configuration parameters
Network
| Parameter | Type | Default | Allowed values | Required | Secret | Restart | Description |
|---|---|---|---|---|---|---|---|
Interface port (port) | port | 8090 | min 1024 | no | no | yes | Port of the nginx component: web interface, REST API and media (1024 or more: nginx runs as a non root user). |
Application port (app_port) | port | 8091 | min 1024 | no | no | yes | uwsgi port of the app component, reached by nginx only: on the network of the service in the standalone mode, from the other hosts of the cluster in the replicated mode. |
Public address (public_url) | string | (empty) | ^(|https?://[A-Za-z0-9.-]+(:[0-9]{1,5})?)$ | no | no | yes | Address the users open, for example https://label-studio.bank.internal behind the gateway (LABEL_STUDIO_HOST and CSRF_TRUSTED_ORIGINS); with https the cookies are secure only. Empty: links relative to the requested host. |
TLS (tls_enabled) | bool | false | - | no | no | yes | Serve the interface, the REST API and the media in HTTPS on the interface port with a certificate of the Manager CA (nginx of the image, TLS 1.2 and 1.3, HSTS); without a public address the cookies are then secure only and the https addresses of the interfaces are the trusted origins. The uwsgi port of the applications stays HTTP: the uwsgi of the image is built without OpenSSL. |
Application
| Parameter | Type | Default | Allowed values | Required | Secret | Restart | Description |
|---|---|---|---|---|---|---|---|
Workers (workers) | int | 4 | min 1, max 32 | no | no | yes | uwsgi worker processes of each app replica. (recommended clamp(floor(host.cpu_count / 2), 2, 16)) |
Maximum upload (max_upload_mb) | int | 200 | min 1, max 10240 | no | no | yes | Largest request body in MB, for nginx (client_max_body_size) and the application (DATA_UPLOAD_MAX_MEMORY_SIZE). |
Log level (log_level) | enum | WARNING | DEBUG, INFO, WARNING, ERROR | no | no | no | Verbosity of the application log (LOG_LEVEL), written as JSON to the journal. |
Security
| Parameter | Type | Default | Allowed values | Required | Secret | Restart | Description |
|---|---|---|---|---|---|---|---|
Administrator account (admin_email) | string | admin@navin.internal | ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+$ | no | no | no | E-mail address of the first account, created at the first start (LABEL_STUDIO_USERNAME); its password is then changed in the interface. |
Administrator password (admin_password) | password | generated | - | no | yes | no | Password of the first account (LABEL_STUDIO_PASSWORD), generated at each install and kept in the Manager vault. |
Secret key (secret_key) | password | generated | - | no | yes | yes | Django SECRET_KEY shared by every replica: it signs the session cookies and the access tokens (changing it signs every user out and revokes the personal access tokens). |
Open sign up (allow_signup) | bool | false | - | no | no | no | Let anyone who reaches the interface create an account. Off (LABEL_STUDIO_DISABLE_SIGNUP_WITHOUT_LINK=true): only the invitation link of the organization registers a user. |
Trusted authorities (trusted_ca_pem) | text | (empty) | (-----BEGIN CERTIFICATE-----\r?\n[A-Za-z0-9+/=\r\n]+-----END CERTIFICATE-----\s*)* | no | no | yes | PEM certificates of the internal authorities that sign the certificates of the database (sslmode verify-ca or verify-full) and of an https S3 storage. The application trusts them in addition to the public authorities of the image; the media proxy of the interface trusts them instead of the public authorities. Empty: public authorities only. |
Internal ML backends (allow_local_ml_backends) | bool | false | - | no | no | yes | Let the projects connect machine learning backends (pre-annotation, active learning) at private addresses of the internal network (ML_BLOCK_LOCAL_IP=false). Off: Label Studio refuses an ML backend that resolves to a private or loopback address. The protection against server side request forgery of the imports by URL, of the webhooks and of the S3 endpoints typed in a project stays on. |
Dependencies
For each active dependency the Manager takes the first of: the binding chosen in the wizard; a service of the same installation that provides it; a service already installed in the cluster; the only connection of the expected type. Otherwise an optional dependency stays unbound, and a required one is added to the installation in its default mode (the column below names the catalog service added).
| Binding | Provided by | Connection type | Endpoint | Optional | When nothing is bound | Description |
|---|---|---|---|---|---|---|
database | postgresql | postgresql | sql | no | postgresql is added to the installation | Database of the projects, tasks, annotations, users and organizations. |
s3 | seaweedfs | s3 | s3 | no | seaweedfs is added to the installation | Bucket of the uploaded media and of the exports (persistent storage shared by every replica). |
Endpoints
| Endpoint | Scheme | Component | Port | Path | TLS parameter | Binding parameters | Binding secrets | Provisioning command |
|---|---|---|---|---|---|---|---|---|
web | http | nginx | 8090 (port) | - | tls_enabled | - | - | - |
Client configuration files
Files rendered for the client configuration download:
label-studio.env(client.env.j2)
Commands
| Command | Component | Target | Description |
|---|---|---|---|
Application logs (logs) | app | chosen host | Last lines of the application journal (migrations, requests in error). |
Interface logs (interface_logs) | nginx | chosen host | Last lines of the nginx journal (JSON access log). |
Readiness (readiness) | app | every host | Checks that every application answers (database reached, migrations applied). |
Versions (version) | app | chosen host | Versions of Label Studio and of its front end and editor as the running application reports them (GET /api/version/). |
Health checks
Liveness (per instance)
| Component | Check | Details |
|---|---|---|
app | HTTP http://127.0.0.1:{{ config.app_port }}/health/ | Expected 200; Expected UP; 120 retries; interval 5 s; timeout 5 s |
nginx | HTTP {{ 'https' if config.tls_enabled else 'http' }}://{{ host.ip or '127.0.0.1' }}:{{ config.port }}/nginx_health | Expected 200; 60 retries; interval 2 s; timeout 5 s |
Readiness (service check)
| Check | Details |
|---|---|
HTTP {{ 'https' if config.tls_enabled else 'http' }}://{{ host.ip or '127.0.0.1' }}:{{ config.port }}/health/ | Expected 200; Expected UP; 10 retries; interval 3 s; timeout 10 s |
Preflight checks
| Check | Type | Meaning | Severity | Components |
|---|---|---|---|---|
memory | memory_mb {"min": 4096} | at least 4096 MB of memory | warning | app |
podman | binary {"name": "podman"} | the program podman installed on the host | blocking | every component |
port_free | port_free {"param": "port"} | port 8090 free on the host | blocking | nginx |
app_port_free | port_free {"param": "app_port"} | port 8091 free on the host | blocking | app |
Uninstall
Paths removed when the data is purged: {{ paths.data }}, {{ paths.log }}.
Quick links
- Label Studio:
{{ (config.public_url ~ '/') if config.public_url else (('https' if config.tls_enabled else 'http') ~ '://' ~ host.fqdn ~ ':' ~ config.port ~ '/') }}
Upstream documentation
- Homepage: https://labelstud.io
- Source: https://github.com/HumanSignal/label-studio
- High availability: https://labelstud.io/guide/persistent_storage
- High availability: https://labelstud.io/guide/storedata
- High availability: https://labelstud.io/guide/install_k8s
- High availability: https://labelstud.io/guide/security
- Authentication: https://labelstud.io/guide/access_tokens