Skip to content

OliveTin

Browser-based interface for running predefined shell commands on Kubernetes. OliveTin lets you expose safe, well-defined system actions — restart a service, trigger a backup, run a diagnostic — as clickable buttons in a clean web UI, without giving users direct shell access.

Do not expose OliveTin to the public internet without authentication

OliveTin executes shell commands on the server. Without authentication, anyone who can reach the URL can run all configured actions. Deploy behind an auth proxy (Authelia, Authentik, Traefik ForwardAuth) or restrict access to a trusted network or VPN.

Key Features

  • ConfigMap-based actions — define shell commands in YAML, mounted as a ConfigMap
  • No external dependencies — no database, no state, stateless by design
  • Prometheus metrics — optional scraping with ServiceMonitor support
  • Confirmation prompts — require user confirmation before running destructive commands
  • Icon and title customization — human-friendly labels for each action
  • Lightweight — minimal resource footprint

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install olivetin helmforge/olivetin

OCI registry:

helm install olivetin oci://ghcr.io/helmforgedev/helm/olivetin

Deployment Examples

# values.yaml — Minimal setup with a few example actions
config: |
  actions:
    - title: "Ping Google"
      shell: "ping -c 1 google.com"
      icon: "ping"

    - title: "Show Disk Usage"
      shell: "df -h"
      icon: "disk"

    - title: "Show Memory"
      shell: "free -h"
      icon: "memory"

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: olivetin.internal.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — Advanced action definitions with confirmation, timeouts, and arguments
config: |
  actions:
    - title: "Restart nginx"
      shell: "kubectl rollout restart deployment/nginx -n web"
      icon: "restart"
      confirmBeforeStart: true
      timeout: 30

    - title: "Trigger Backup"
      shell: "kubectl create job backup-manual --from=cronjob/database-backup -n database"
      icon: "backup"
      confirmBeforeStart: true
      timeout: 60

    - title: "Get Pod Logs"
      shell: "kubectl logs -n {{ namespace }} {{ pod }} --tail=100"
      icon: "logs"
      arguments:
        - name: namespace
          title: "Namespace"
          default: default
        - name: pod
          title: "Pod name"

    - title: "Scale Deployment"
      shell: "kubectl scale deployment {{ deployment }} --replicas={{ replicas }} -n {{ namespace }}"
      icon: "scale"
      confirmBeforeStart: true
      arguments:
        - name: namespace
          title: "Namespace"
          default: default
        - name: deployment
          title: "Deployment"
        - name: replicas
          title: "Replica count"
          default: "1"

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: olivetin.internal.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — OliveTin with Prometheus metrics and ServiceMonitor
config: |
  actions:
    - title: "Ping Google"
      shell: "ping -c 1 google.com"

metrics:
  enabled: true
  serviceMonitor:
    enabled: true
    interval: 30s
    scrapeTimeout: 10s

ingress:
  enabled: true
  ingressClassName: traefik
  hosts:
    - host: olivetin.internal.example.com
      paths:
        - path: /
          pathType: Prefix
# values.yaml — OliveTin behind Traefik ForwardAuth (Authelia example)
config: |
  actions:
    - title: "Ping Google"
      shell: "ping -c 1 google.com"

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    traefik.ingress.kubernetes.io/router.middlewares: auth-authelia-forwardauth@kubernetescrd
  hosts:
    - host: olivetin.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: olivetin-tls
      hosts:
        - olivetin.example.com

Configuration Reference

Core

ParameterTypeDefaultDescription
nameOverridestring""Override the chart name.
fullnameOverridestring""Override the full release name.
commonLabelsobject{}Extra labels added to all resources.

Image

ParameterTypeDefaultDescription
image.repositorystringdocker.io/jamesread/olivetinOliveTin container image.
image.tagstring"3000.11.3"Image tag.
image.pullPolicystringIfNotPresentImage pull policy.
imagePullSecretsarray[]Pull secrets for private registries.

OliveTin Configuration

ParameterTypeDefaultDescription
olivetin.portinteger1337Internal HTTP port for the OliveTin container.
olivetin.extraEnvarray[]Extra environment variables injected into the container.
configstring(default ping action)OliveTin YAML configuration mounted at /config/config.yaml.
config is mounted as a ConfigMap

The entire config block is stored in a Kubernetes ConfigMap and mounted at /config/config.yaml. Any change to config during a Helm upgrade will trigger a pod restart to pick up the new configuration. Keep action definitions in version control alongside your values files.

The config block supports the full OliveTin configuration schema. Key action options:

Action FieldDescription
titleDisplay name shown on the button in the web UI.
shellShell command to execute.
iconButton icon name (uses OliveTin’s built-in icon set).
confirmBeforeStartShow a confirmation dialog before executing (default: false).
timeoutExecution timeout in seconds (default: 3).
argumentsList of user-provided arguments interpolated into shell via {{ }}.

See the full OliveTin configuration reference for all available options.

Metrics

ParameterTypeDefaultDescription
metrics.enabledbooleanfalseEnable Prometheus metrics scraping annotations.
metrics.serviceMonitor.enabledbooleanfalseCreate a ServiceMonitor for Prometheus Operator.
metrics.serviceMonitor.namespacestring""Namespace for the ServiceMonitor (defaults to chart).
metrics.serviceMonitor.labelsobject{}Extra labels applied to the ServiceMonitor.
metrics.serviceMonitor.intervalstring30sPrometheus scrape interval.
metrics.serviceMonitor.scrapeTimeoutstring10sPrometheus scrape timeout.

Persistence

OliveTin is stateless — the config lives in a ConfigMap, and action logs are ephemeral. Persistence is optional and only needed if your actions produce output files that must survive pod restarts.

ParameterTypeDefaultDescription
persistence.enabledbooleanfalseEnable a PVC for custom data or output files.
persistence.sizestring1GiPVC size.
persistence.storageClassstring""StorageClass for the PVC.
persistence.accessModesarray["ReadWriteOnce"]PVC access modes.
persistence.existingClaimstring""Use an existing PVC instead of creating one.

Service

ParameterTypeDefaultDescription
service.typestringClusterIPKubernetes service type.
service.portinteger80Service port exposed to the cluster.
service.annotationsobject{}Annotations for the Service.

Ingress

ParameterTypeDefaultDescription
ingress.enabledbooleanfalseEnable an Ingress resource.
ingress.ingressClassNamestringtraefikIngress class name.
ingress.annotationsobject{}Annotations for the Ingress (e.g. ForwardAuth, TLS).
ingress.hostsarray[]Ingress host and path rules.
ingress.tlsarray[]TLS configuration (secret name and hosts).

Probes

ParameterTypeDefaultDescription
probes.startup.enabledbooleantrueEnable startup probe.
probes.startup.initialDelaySecondsinteger5Startup probe initial delay.
probes.startup.periodSecondsinteger5Startup probe period.
probes.startup.timeoutSecondsinteger3Startup probe timeout.
probes.startup.failureThresholdinteger30Startup probe failure threshold.
probes.liveness.enabledbooleantrueEnable liveness probe.
probes.liveness.initialDelaySecondsinteger0Liveness probe initial delay.
probes.liveness.periodSecondsinteger15Liveness probe period.
probes.liveness.timeoutSecondsinteger5Liveness probe timeout.
probes.liveness.failureThresholdinteger3Liveness probe failure threshold.
probes.readiness.enabledbooleantrueEnable readiness probe.
probes.readiness.initialDelaySecondsinteger0Readiness probe initial delay.
probes.readiness.periodSecondsinteger10Readiness probe period.
probes.readiness.timeoutSecondsinteger5Readiness probe timeout.
probes.readiness.failureThresholdinteger3Readiness probe failure threshold.

Resources and Security

ParameterTypeDefaultDescription
resourcesobject{}CPU and memory requests and limits.
podSecurityContextobject{}Pod-level security context.
securityContextobject{}Container-level security context.

Service Account

ParameterTypeDefaultDescription
serviceAccount.createbooleanfalseCreate a dedicated ServiceAccount.
serviceAccount.namestring""Override the ServiceAccount name.
serviceAccount.annotationsobject{}Annotations for the ServiceAccount.

Scheduling

ParameterTypeDefaultDescription
nodeSelectorobject{}Node selector for scheduling.
tolerationsarray[]Tolerations for scheduling.
affinityobject{}Affinity rules.
topologySpreadConstraintsarray[]Topology spread constraints.
priorityClassNamestring""PriorityClass for the pod.
terminationGracePeriodSecondsinteger30Termination grace period.
podLabelsobject{}Extra labels for the pod.
podAnnotationsobject{}Extra annotations for the pod.

Extra

ParameterTypeDefaultDescription
extraVolumesarray[]Extra volumes to attach to the pod.
extraVolumeMountsarray[]Extra volume mounts for the container.
extraManifestsarray[]Extra Kubernetes manifests deployed alongside the chart.

Common Issues

Actions timing out unexpectedly

The default action timeout in OliveTin is 3 seconds. Long-running commands (kubectl rollouts, database backups) will appear to succeed in the UI but be killed silently. Set timeout explicitly in each action that needs more time.

Run kubectl commands from OliveTin

To run kubectl commands, the OliveTin pod needs cluster access. Create a ServiceAccount with appropriate RBAC permissions and set serviceAccount.create: true with serviceAccount.annotations pointing to the account. Mount the kubeconfig or rely on in-cluster config.

More Information