Skip to content

How to submit your own application

王贺 edited this page Mar 6, 2026 · 1 revision

Add the App You Want

You should be familiar with Docker and Docker Compose.

Prerequisites

  • The project should be actively maintained and open source.
  • An official Docker image should be available.

1. Fork This Repository

To submit a pull request, first fork this repository. Go to appstore, click the Fork button in the top-right corner, and fork it into your own GitHub account.

2. Clone the Repository Locally

Run the command below to clone the code to your machine:

git clone -b dev https://<your-github-username>/appstore

3. Create a New Branch

Go to the cloned directory:

cd appstore

Create a new branch:

git checkout -b app/<app-name>

4. Create App Files (Halo as an Example)

For v1.3 and later, you can quickly scaffold app files on the 1Panel host with:

1panel app init <app-key> <app-version>

Note: use 1panel, not 1pctl.

Folder structure:

├── halo                     // Named by app key (explained below)
│   ├── logo.png             // App logo, ideally 180x180 px, <= 10 KB
│   ├── data.yml             // App metadata file
│   ├── README.md            // App README
│   ├── 2.2.0                // App version (do not prefix with "v")
│   │   ├── data.yml         // Version-level form/config (explained below)
│   │   ├── data             // Mounted data directory
│   │   ├── scripts          // Script directory: init.sh, upgrade.sh, uninstall.sh
│   │   └── docker-compose.yml
│   └── 2.3.2
│       ├── data.yml
│       ├── data
│       └── docker-compose.yml

App metadata file: data.yml

This file defines app-level metadata.

additionalProperties:  # fixed field
  key: halo            # app key, English only, used to create Linux directories
  name: Halo           # app display name
  tags:
    - WebSite          # app tags, supports multiple values (see tag table below)
  description:
    en: Powerful and easy-to-use open source website builder
    zh: 强大易用的开源建站工具 # Chinese description, keep it under 30 characters
    zh-Hant:
    ja:
    ms:
    pt-br:
    ru:
    ko:
  type: website        # app type (not the same as tag), single value only
  crossVersionUpdate: true  # whether major-version upgrade is allowed
  limit: 0             # install limit, 0 means unlimited
  website: https://halo.run/  # official website
  github: https://github.com/halo-dev/halo # GitHub URL
  document: https://docs.halo.run/ # documentation URL

App tags (tags) (continuously updated):

key name
WebSite Website
Server Web Server
Runtime Runtime
Database Database
Tool Tool
CI/CD CI/CD
Local Local

App type (type):

type Description
website Supports one-click deployment under Websites in 1Panel. wordpress and halo are examples.
runtime Runtime-type apps such as mysql, openresty, redis.
tool Tool-type apps such as phpMyAdmin, redis-commander, jenkins.

App parameter config file: data.yml (inside each version directory)

Do not confuse this with the app root data.yml. This file is mainly used to generate the installation form. Even if no form is needed, this file must exist and include the formFields field.

Using Halo's install form as an example:

iShot_2023-03-18_14 03 43

To generate the form above, the version-level data.yml can be defined like this:

additionalProperties:  # fixed field
  formFields:
    - default: ""
      envKey: PANEL_DB_HOST  # variable used in docker-compose
      key: mysql             # dependency app key, e.g. mysql
      label:
        en: Database Service
        ja: データベースサービス
        ms: Perkhidmatan Pangkalan Data
        pt-br: Serviço de Banco de Dados
        ru: Сервис базы данных
        ko: 데이터베이스 서비스
        zh: 数据库服务
        zh-Hant: 數據庫 服務
      required: true
      type: service          # use when depending on another app (e.g. DB)
    - default: halo
      envKey: PANEL_DB_NAME
      label:
        en: Database
        ja: データベース
        ms: Pangkalan Data
        pt-br: Banco de Dados
        ru: База данных
        ko: 데이터베이스
        zh: 数据库名
        zh-Hant: 資料庫名稱
      random: true           # append random string after default value
      required: true
      rule: paramCommon
      type: text             # manually input text
    - default: halo
      envKey: PANEL_DB_USER
      label:
        en: User
        ja: ユーザー
        ms: Pengguna
        pt-br: Usuário
        ru: Пользователь
        ko: 사용자
        zh: 数据库用户
        zh-Hant: 資料庫使用者
      random: true
      required: true
      rule: paramCommon
      type: text
    - default: halo
      envKey: PANEL_DB_USER_PASSWORD
      label:
        en: Password
        ja: パスワード
        ms: Kata laluan
        pt-br: Senha
        ru: Пароль
        ko: 비밀번호
        zh: 数据库用户密码
        zh-Hant: 資料庫使用者密碼
      random: true
      required: true
      rule: paramComplexity
      type: password         # use for password fields
    - default: admin
      envKey: HALO_ADMIN
      labelEn: Admin Username
      labelZh: 超级管理员用户名
      required: true
      rule: paramCommon
      type: text
    - default: http://localhost:8080
      edit: true
      envKey: HALO_EXTERNAL_URL
      label:
        en: External URL
        ja: 外部URL
        ms: URL Luaran
        pt-br: URL Externa
        ru: Внешний URL
        ko: 외부 URL
        zh: 外部访问地址
        zh-Hant: 外部訪問地址
      required: true
      rule: paramExtUrl
      type: text
    - default: 8080
      edit: true
      envKey: PANEL_APP_PORT_HTTP
      label:
        en: Port
        ja: ポート
        ms: Port
        pt-br: Porta
        ru: Порт
        ko: 포트
        zh: 端口
        zh-Hant: 
      required: true
      rule: paramPort
      type: number           # use number for port fields

About port fields:

  1. If the app exposes a web port, prefer PANEL_APP_PORT_HTTP as the envKey.
  2. Any envKey with the PANEL_APP_PORT prefix is treated as a port field and will be validated for port conflicts before installation. Note: this must be the external port.

About the type field:

type Description
service type: service means the app depends on another component (for example, MySQL or Redis). Define the dependency name using key: mysql, and users will be prompted to create/select the dependency first.
password type: password is for sensitive fields. Values are masked by default.
text type: text is for regular fields such as database name, shown in plain text.
number type: number is typically used for port settings and accepts digits only.
select type: select is for options such as true/false, log levels, and similar enums.

Simple examples:

# type: service, define a MySQL service dependency
- child:
    default: ""
    envKey: PANEL_DB_HOST
    required: true
    type: service
  default: mysql
  envKey: PANEL_DB_TYPE
  label:
    en: Database Service
    ja: データベースサービス
    ms: Perkhidmatan Pangkalan Data
    pt-br: Serviço de Banco de Dados
    ru: Сервис баз данных
    ko: 데이터베이스 서비스
    zh-hant: 資料庫服務
    zh: 数据库服务
  required: true
  type: apps
  values:
    - label: MySQL
      value: mysql
    - label: MariaDB
      value: mariadb

# type: password
- default: word
  envKey: PANEL_DB_USER_PASSWORD
  labelEn: Database Password
  labelZh: 数据库密码
  label:
    en: Database Password
    ja: データベースのパスワード
    ms: Kata Laluan Pangkalan Data
    pt-br: Senha do Banco de Dados
    ru: Пароль базы данных
    ko: 데이터베이스 비밀번호
    zh-hant: 資料庫密碼
    zh: 数据库密码
  random: true
  required: true
  type: password

# type: text
- default: ""
  edit: true
  envKey: REDIS_HOST
  key: redis
  required: true
  type: service
  label:
    en: Redis Service
    ja: Redis サービス
    ms: Perkhidmatan Redis
    pt-br: Serviço Redis
    ru: Сервис Redis
    ko: Redis 서비스
    zh-Hant: Redis 服務
    zh: Redis 服务

# type: number
- default: ""
  edit: true
  envKey: DBHUB_DB_PORT
  required: true
  type: text
  label:
    en: Database Port
    ja: データベースのポート
    ms: Pangkalan Data Port
    pt-br: Porta do Banco de Dados
    ru: Порт базы данных
    ko: 데이터베이스 포트
    zh-hant: 資料庫端口
    zh: 数据库端口

# type: select
- default: "ERROR"
  envKey: LOG_LEVEL
  required: true
  type: select
  values:
    - label: DEBUG
      value: "DEBUG"
    - label: INFO
      value: "INFO"
    - label: WARNING
      value: "WARNING"
    - label: ERROR
      value: "ERROR"
    - label: CRITICAL
      value: "CRITICAL"

Supported validation rules (rule):

rule Validation
paramPort Limits port range to 1-65535.
paramExtUrl Must match http(s)://(domain/ip):(port).
paramCommon Letters, numbers, ., -, _, length 2-30.
paramComplexity Supports letters, numbers, .%@$!&~_-, length 6-30; special characters cannot appear at the beginning or end.

App docker-compose.yml

Variables like ${PANEL_APP_PORT_HTTP} should be declared in the version-level data.yml.

version: "3"
services:
  halo:
    image: halohub/halo:2.2.0
    container_name: ${CONTAINER_NAME}  // fixed syntax, do not change
    restart: always
    networks:
      - 1panel-network  // apps created by 1Panel are attached to this network
    volumes:
      - ./data:/root/.halo2
    ports:
      - ${PANEL_APP_PORT_HTTP}:8090
    command:
      - --spring.r2dbc.url=r2dbc:pool:${HALO_PLATFORM}://${PANEL_DB_HOST}:${HALO_DB_PORT}/${PANEL_DB_NAME}
      - --spring.r2dbc.username=${PANEL_DB_USER}
      - --spring.r2dbc.password=${PANEL_DB_USER_PASSWORD}
      - --spring.sql.init.platform=${HALO_PLATFORM}
      - --halo.external-url=${HALO_EXTERNAL_URL}
      - --halo.security.initializer.superadminusername=${HALO_ADMIN}
      - --halo.security.initializer.superadminpassword=${HALO_ADMIN_PASSWORD}
    labels:
      createdBy: "Apps"

networks:
  1panel-network:
    external: true

5. Scripts

1Panel supports running .sh scripts before install, before upgrade, and after uninstall:

  • init.sh
  • upgrade.sh
  • uninstall.sh

Script location (Halo example): halo/2.2.0/scripts

6. Local Testing

Upload the app directory to:

/opt/1panel/resource/apps/local

Note: /opt is the default 1Panel install path. Adjust it if your installation path is different.

After upload, the directory should look like this:

├── halo
│   ├── logo.png
│   ├── data.yml
│   ├── README.md
│   └── 2.2.0
│       ├── data.yml
│       ├── data
│       └── docker-compose.yml

In the 1Panel App Store, click Update App List to sync local apps.

For local apps created in v1.2 or earlier, see this guide.

7. Commit Your Changes

git add .
git commit -m "Add my-app"
git push origin dev

8. Submit a Pull Request

  • Open the Pull requests tab in your fork.
  • Click New pull request and fill in the title and description.
  • Submit from your branch to 1Panel-dev/appstore.