deletes everything
This commit is contained in:
122
.github/README.md
vendored
122
.github/README.md
vendored
@@ -1,122 +0,0 @@
|
|||||||
|
|
||||||
<h1 align="center">Portainer Templates</h1>
|
|
||||||
<p align="center"><i>A compiled list of 400+ ready to go Portainer App templates</i></p>
|
|
||||||
<p align="center">
|
|
||||||
<img width="200" src="https://i.ibb.co/hMymwH0/portainer-templates-small.png" />
|
|
||||||
</p>
|
|
||||||
|
|
||||||
> **TL;DR** Under Settings → App Templates in your Portainer GUI, paste this URL:<br>
|
|
||||||
> `https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json`<br>
|
|
||||||
|
|
||||||
|
|
||||||
## Intro
|
|
||||||
|
|
||||||
In Portainer, [App Templates](https://docs.portainer.io/user/docker/templates) enable you to easily deploy a container with a predetermined configuration, while allowing you to customize options through the web UI. Both single containers, and stacks are supported. While Portainer ships with some default templates (see [portainer/templates](https://github.com/portainer/templates)), it's often helpful to have 1-click access to many more apps, without having to constantly switch template sources.
|
|
||||||
|
|
||||||
This repo combines app templates from several [sources](#sources), to create a ready-to-go template file containing all the apps you'll ever need.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
1. Log into your Portainer web UI
|
|
||||||
2. Under Settings --> App Templates, update the URL to
|
|
||||||
- `https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json`
|
|
||||||
3. Now under Home --> App Templates, you should see all apps. Click one to deploy.
|
|
||||||
|
|
||||||
Alternatively, when you start Portainer, you can append the `--templates` flag pointing to the templates URL.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Self-Hosting
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://github.com/lissy93/portainer-templates.git portainer-templates
|
|
||||||
cd portainer-templates
|
|
||||||
docker build -t portainer-templates .
|
|
||||||
docker run -d -p "8080:80" portainer-templates
|
|
||||||
```
|
|
||||||
|
|
||||||
Your templates file will then be served up, at: `http://docker-host:8080/templates.json`
|
|
||||||
|
|
||||||
Or, to mount the `templates.json` file to your container, so that you can make changes to it, and have them show up within Portainer
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -d -p "8080:80" -v "${PWD}/templates.json:/usr/share/nginx/html/templates.json" portainer-templates
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Editing
|
|
||||||
|
|
||||||
The `template.json` file is generated using the scripts in [`lib`](https://github.com/Lissy93/portainer-templates/tree/main/lib), using GitHub Actions.
|
|
||||||
Running the `make` command will download all listed sources, parse them, and combine them outputting the `templates.json` file.
|
|
||||||
|
|
||||||
### Adding a new Source
|
|
||||||
Just place a link to the source, along with your chosen name in the [`sources.csv`](https://github.com/Lissy93/portainer-templates/blob/main/sources.csv) file.
|
|
||||||
When the action runs, it will download the content, parse it and add it to the final template.
|
|
||||||
|
|
||||||
### Adding a Template / Template list
|
|
||||||
Alternatively, place your template file within the [`sources`](https://github.com/Lissy93/portainer-templates/tree/main/sources) directory, and it will be automatically combined into the main `template.json`.
|
|
||||||
Be sure that your template corresponds to [Portainer's App Template JSON Format](https://docs.portainer.io/advanced/app-templates/format).
|
|
||||||
|
|
||||||
### Validating Templates
|
|
||||||
There is a schema defined in [`Schema.json`](https://github.com/Lissy93/portainer-templates/blob/main/Schema.json), which can be used to validate any Portainer template.
|
|
||||||
Run `make validate` to ensure your template conforms to Portainer's App Template [specification](https://docs.portainer.io/advanced/app-templates/format).
|
|
||||||
|
|
||||||
### Maintaining your own Templates
|
|
||||||
If you'd prefer to maintain your own templates, while using the templates included here as a base, then fork the repository, and update `lissy93` with your GitHub username
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Sources
|
|
||||||
|
|
||||||
The templates here are composed from the following sources. Full credit to the authors of each
|
|
||||||
|
|
||||||
- [dnburgess](https://github.com/dnburgess/self-hosted-template) <sup>[`template.json`](https://raw.githubusercontent.com/dnburgess/self-hosted-template/master/template.json)</sup>
|
|
||||||
- [qballjos](https://github.com/Qballjos/portainer_templates) <sup>[`template.json`](https://raw.githubusercontent.com/Qballjos/portainer_templates/master/Template/template.json)</sup>
|
|
||||||
- [SelfhostedPro](https://github.com/SelfhostedPro/selfhosted_templates) <sup>[`template.json`](https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/portainer-2.0/Template/template.json)</sup>
|
|
||||||
- [technorabilia](https://github.com/technorabilia/portainer-templates) <sup>[`template.json`](https://raw.githubusercontent.com/technorabilia/portainer-templates/main/lsio/templates/templates-2.0.json)</sup>
|
|
||||||
- [mikestraney](https://github.com/mikestraney/portainer-templates) <sup>[`template.json`](https://raw.githubusercontent.com/mikestraney/portainer-templates/master/templates.json)</sup>
|
|
||||||
- [xneo1](https://github.com/xneo1/portainer_templates) <sup>[`template.json`](https://raw.githubusercontent.com/xneo1/portainer_templates/master/Template/template.json)</sup>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Supported Apps and Stacks
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Disclaimer
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- License + Copyright -->
|
|
||||||
<p align="center">
|
|
||||||
<i>© <a href="https://aliciasykes.com">Alicia Sykes</a> 2023</i><br>
|
|
||||||
<i>Licensed under <a href="https://gist.github.com/Lissy93/143d2ee01ccc5c052a17">MIT</a></i><br>
|
|
||||||
<a href="https://github.com/lissy93"><img src="https://i.ibb.co/4KtpYxb/octocat-clean-mini.png" /></a><br>
|
|
||||||
<sup>Thanks for visiting :)</sup>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Dinosaur -->
|
|
||||||
<!--
|
|
||||||
. - ~ ~ ~ - .
|
|
||||||
.. _ .-~ ~-.
|
|
||||||
//| \ `..~ `.
|
|
||||||
|| | } } / \ \
|
|
||||||
(\ \\ \~^..' | } \
|
|
||||||
\`.-~ o / } | / \
|
|
||||||
(__ | / | / `.
|
|
||||||
`- - ~ ~ -._| /_ - ~ ~ ^| /- _ `.
|
|
||||||
| / | / ~-. ~- _
|
|
||||||
|_____| |_____| ~ - . _ _~_-_
|
|
||||||
-->
|
|
||||||
|
|
||||||
47
.github/workflows/build-template.yml
vendored
47
.github/workflows/build-template.yml
vendored
@@ -1,47 +0,0 @@
|
|||||||
name: 🏗️ Build + Publish templates.json file
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: [ main ]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# Checkout repo
|
|
||||||
- name: Checkout repository 🛎️
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Get current date-time (used for commit message)
|
|
||||||
- name: Get Date 📅
|
|
||||||
id: date
|
|
||||||
run: echo "::set-output name=date::$(date +'%d-%b-%Y')"
|
|
||||||
|
|
||||||
# Downloads + installs Python (used for running gen scripts)
|
|
||||||
- name: Set up Python 🐍
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: '3.x'
|
|
||||||
|
|
||||||
# Install contents of requirements.txt
|
|
||||||
- name: Install dependencies 📥
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
cd lib && pip install -r requirements.txt
|
|
||||||
|
|
||||||
# The make command triggers all the Python scripts, generates output
|
|
||||||
- name: Run make command 🔨
|
|
||||||
run: make
|
|
||||||
|
|
||||||
# Commit and push the outputed JSON files
|
|
||||||
- name: Commit and push generated files ⤴️
|
|
||||||
run: |
|
|
||||||
git config --global user.name "Liss-Bot"
|
|
||||||
git config --global user.email "alicia-gh-bot@mail.as93.net"
|
|
||||||
git add templates.json
|
|
||||||
if git diff --staged --quiet; then
|
|
||||||
echo "Nothin new added, so nothing to commit, exiting..."
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
git commit -m "Updates templates (auto-generated, on ${{ steps.date.outputs.date }})"
|
|
||||||
git push
|
|
||||||
fi
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
FROM nginx:stable-alpine
|
|
||||||
|
|
||||||
COPY templates.json /usr/share/nginx/html/templates.json
|
|
||||||
|
|
||||||
EXPOSE 80
|
|
||||||
15
Makefile
15
Makefile
@@ -1,15 +0,0 @@
|
|||||||
.PHONY: all install_requirements download combine
|
|
||||||
|
|
||||||
all: install_requirements download combine
|
|
||||||
|
|
||||||
install_requirements:
|
|
||||||
pip install -r lib/requirements.txt
|
|
||||||
|
|
||||||
download:
|
|
||||||
python lib/download.py
|
|
||||||
|
|
||||||
combine:
|
|
||||||
python lib/combine.py
|
|
||||||
|
|
||||||
validate:
|
|
||||||
python lib/validate.py
|
|
||||||
112
Schema.json
112
Schema.json
@@ -1,112 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"type": "object",
|
|
||||||
"title": "PortainerAppTemplate",
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The version of the Portainer App Template."
|
|
||||||
},
|
|
||||||
"templates": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 2,
|
|
||||||
"description": "The type of the application (1 for container, 2 for swarm stack)."
|
|
||||||
},
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The title of the application."
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "A brief description of the application."
|
|
||||||
},
|
|
||||||
"categories": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1
|
|
||||||
},
|
|
||||||
"description": "An array of categories the application belongs to."
|
|
||||||
},
|
|
||||||
"platform": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The target platform of the application (e.g., 'linux', 'windows')."
|
|
||||||
},
|
|
||||||
"logo": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri",
|
|
||||||
"description": "A URI to the logo of the application."
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The name of the Docker image used for the application."
|
|
||||||
},
|
|
||||||
"restart_policy": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["always", "unless-stopped", "on-failure", "no"],
|
|
||||||
"description": "The restart policy for the application."
|
|
||||||
},
|
|
||||||
"ports": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[0-9]+:[0-9]+(/tcp|/udp)?$",
|
|
||||||
"description": "A port mapping in the format 'hostPort:containerPort/protocol'."
|
|
||||||
},
|
|
||||||
"description": "An array of port mappings for the application."
|
|
||||||
},
|
|
||||||
"volumes": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"bind": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The host path for the volume binding."
|
|
||||||
},
|
|
||||||
"container": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The container path for the volume binding."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["bind", "container"]
|
|
||||||
},
|
|
||||||
"description": "An array of volume mappings for the application."
|
|
||||||
},
|
|
||||||
"environment": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"description": "The name of the environment variable."
|
|
||||||
},
|
|
||||||
"label": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["type", "title", "description", "categories", "platform", "logo", "image"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["version", "templates"]
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import os
|
|
||||||
import json
|
|
||||||
|
|
||||||
# Get list of files in sources
|
|
||||||
dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
templates_src_dir = os.path.join(dir, '../sources/')
|
|
||||||
template_dest_file = os.path.join(dir, '../templates.json')
|
|
||||||
|
|
||||||
files = os.listdir(templates_src_dir)
|
|
||||||
|
|
||||||
# Initialize empty list to store template objects
|
|
||||||
templates = []
|
|
||||||
|
|
||||||
# For each file in sources
|
|
||||||
for file in files:
|
|
||||||
# Open the file
|
|
||||||
with open(templates_src_dir + file) as f:
|
|
||||||
if file.endswith('.json'):
|
|
||||||
# Load the JSON into a variable
|
|
||||||
data = json.load(f)['templates']
|
|
||||||
# Append the template object to the templates list
|
|
||||||
templates = templates + data
|
|
||||||
|
|
||||||
# Remove duplicates
|
|
||||||
seen_titles = set()
|
|
||||||
filtered_data = [x for x in templates if x['title'] not in seen_titles and not seen_titles.add(x['title'])]
|
|
||||||
|
|
||||||
fileData = {
|
|
||||||
'version': '2',
|
|
||||||
'templates': filtered_data
|
|
||||||
}
|
|
||||||
|
|
||||||
# Open the templates.json file, and write results to it
|
|
||||||
with open(template_dest_file, 'w') as f:
|
|
||||||
json.dump(fileData, f, indent=2, sort_keys=False)
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import os
|
|
||||||
import csv
|
|
||||||
import requests
|
|
||||||
|
|
||||||
dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
destination_dir = os.path.join(dir, '../sources')
|
|
||||||
sources_list = os.path.join(dir, '../sources.csv')
|
|
||||||
|
|
||||||
# Downloads the file from a given URL, to the local destination
|
|
||||||
def download(url: str, filename: str):
|
|
||||||
file_path = os.path.join(destination_dir, filename)
|
|
||||||
r = requests.get(url, stream=True)
|
|
||||||
if r.ok:
|
|
||||||
print('saving to', os.path.abspath(file_path))
|
|
||||||
with open(file_path, 'wb') as f:
|
|
||||||
for chunk in r.iter_content(chunk_size=1024 * 8):
|
|
||||||
if chunk:
|
|
||||||
f.write(chunk)
|
|
||||||
f.flush()
|
|
||||||
os.fsync(f.fileno())
|
|
||||||
else: # HTTP status code 4XX/5XX
|
|
||||||
print('Download failed: status code {}\n{}'.format(r.status_code, r.text))
|
|
||||||
|
|
||||||
# Gets list of URLs to download from CSV file
|
|
||||||
def get_source_list():
|
|
||||||
sources=[]
|
|
||||||
with open(sources_list, mode='r') as file:
|
|
||||||
csvFile = csv.reader(file)
|
|
||||||
for lines in csvFile:#
|
|
||||||
sources.append(lines)
|
|
||||||
return sources
|
|
||||||
|
|
||||||
# Create destination folder if not yet present
|
|
||||||
if not os.path.exists(destination_dir):
|
|
||||||
os.makedirs(destination_dir)
|
|
||||||
|
|
||||||
# For each source, download the templates JSON file
|
|
||||||
for sourceUrl in get_source_list():
|
|
||||||
download(sourceUrl[1], sourceUrl[0] + '.json')
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
requests
|
|
||||||
jsonschema
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from jsonschema import validate, ValidationError
|
|
||||||
|
|
||||||
def load_json_file(file_path):
|
|
||||||
with open(file_path, 'r') as file:
|
|
||||||
return json.load(file)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
try:
|
|
||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
schema_file = os.path.join(script_dir, '..', 'Schema.json')
|
|
||||||
templates_file = os.path.join(script_dir, '..', 'templates.json')
|
|
||||||
|
|
||||||
schema = load_json_file(schema_file)
|
|
||||||
templates = load_json_file(templates_file)
|
|
||||||
|
|
||||||
validate(instance=templates, schema=schema)
|
|
||||||
|
|
||||||
print('✅ templates.json is valid against the schema')
|
|
||||||
|
|
||||||
except ValidationError as ve:
|
|
||||||
print('Validation error:', ve.message)
|
|
||||||
sys.exit(1)
|
|
||||||
except FileNotFoundError as fnfe:
|
|
||||||
print(f'File not found error: {fnfe}')
|
|
||||||
sys.exit(1)
|
|
||||||
except json.JSONDecodeError as jde:
|
|
||||||
print(f'JSON decoding error: {jde}')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
dnburgess_templates, https://raw.githubusercontent.com/dnburgess/self-hosted-template/master/template.json
|
|
||||||
qballjos_templates, https://raw.githubusercontent.com/Qballjos/portainer_templates/master/Template/template.json
|
|
||||||
selfhostedpro_templates, https://raw.githubusercontent.com/SelfhostedPro/selfhosted_templates/portainer-2.0/Template/template.json
|
|
||||||
technorabilia_templates, https://raw.githubusercontent.com/technorabilia/portainer-templates/main/lsio/templates/templates-2.0.json
|
|
||||||
mikestraney_templates, https://raw.githubusercontent.com/mikestraney/portainer-templates/master/templates.json
|
|
||||||
xneo1_templates, https://raw.githubusercontent.com/xneo1/portainer_templates/master/Template/template.json
|
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2",
|
|
||||||
"templates": []
|
|
||||||
}
|
|
||||||
15386
templates.json
15386
templates.json
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user