45 Commits

Author SHA1 Message Date
Liss-Bot
9c277ec367 Updates template + source list in docs (auto-generated, on 24-Apr-2023) 2023-04-24 19:50:44 +00:00
Liss-Bot
d7b7e9103c Updates templates (auto-generated, on 24-Apr-2023) 2023-04-24 19:50:43 +00:00
Alicia Sykes
9db9555fad Adds custom stack for get-outline 2023-04-24 20:49:44 +01:00
Alicia Sykes
fc619d5aad Ignores dirs 2023-04-24 20:03:50 +01:00
Liss-Bot
27ec4d928a Updates templates (auto-generated, on 24-Apr-2023) 2023-04-24 14:46:08 +00:00
Alicia Sykes
f960bae2fc Updates raw JSON link for CodeBerg mirror 2023-04-24 15:45:44 +01:00
Alicia Sykes
933e1d105c Minification of index styling 2023-04-23 23:03:52 +01:00
Alicia Sykes
62a857fb7d Updates self-hosted edition usage instructions 2023-04-23 22:59:35 +01:00
Alicia Sykes
5d929935b6 Update publish-docker.yml 2023-04-23 22:38:14 +01:00
Alicia Sykes
31615ce6b5 Updates to Dockerfile 2023-04-23 22:36:00 +01:00
Alicia Sykes
fcbdcc2a57 Updates branch name (main, not master) 2023-04-23 22:35:46 +01:00
Alicia Sykes
26cbcfeaa2 Merge branch 'main' of github.com:lissy93/portainer-templates 2023-04-23 22:34:49 +01:00
Alicia Sykes
7e14e79693 Updates to Dockerfile 2023-04-23 22:34:42 +01:00
Alicia Sykes
504f2dbf6a Enable re-build on Dockerfile changes 2023-04-23 22:33:51 +01:00
Alicia Sykes
11ec48de38 Adds an index for the self-hosted version 2023-04-23 22:32:36 +01:00
Alicia Sykes
49a8ec67d8 Update publish-docker.yml 2023-04-23 22:20:52 +01:00
Alicia Sykes
d7d7add504 Update publish-docker.yml 2023-04-23 22:18:00 +01:00
Alicia Sykes
ccd55a4e9f Updates the tagging functionality of Docker 2023-04-23 22:11:24 +01:00
Alicia Sykes
f8a1c71af7 Use letset tag, when not a release 2023-04-23 21:53:05 +01:00
Alicia Sykes
8a8607bde0 Create file for Docker deployment 2023-04-23 21:47:39 +01:00
Alicia Sykes
caa71aef4e Adds link to non-GH mirror + updates license content 2023-04-23 16:54:13 +01:00
Alicia Sykes
14665db94b Add an action to mirror to CodeBerg 2023-04-23 16:40:17 +01:00
Liss-Bot
e038434162 Updates template + source list in docs (auto-generated, on 23-Apr-2023) 2023-04-23 15:35:37 +00:00
Liss-Bot
9d54e15cc6 Updates templates (auto-generated, on 23-Apr-2023) 2023-04-23 15:35:36 +00:00
Alicia Sykes
f33427dcb3 Run the make, build and publish as a weekly cron 2023-04-23 16:35:13 +01:00
Alicia Sykes
7605e462ff Update README.md 2023-04-22 22:45:03 +01:00
Alicia Sykes
c5d6ec0f29 Update README.md 2023-04-22 22:40:32 +01:00
Liss-Bot
54b7623dce Updates template + source list in docs (auto-generated, on 22-Apr-2023) 2023-04-22 21:30:41 +00:00
Liss-Bot
c918a2d406 Updates templates (auto-generated, on 22-Apr-2023) 2023-04-22 21:30:40 +00:00
Alicia Sykes
046068060a Updates list action, to generate correct hyperlinks 2023-04-22 22:30:15 +01:00
Liss-Bot
a712d9439c Updates template + source list in docs (auto-generated, on 18-Apr-2023) 2023-04-18 17:51:18 +00:00
Alicia Sykes
c4e0185c46 Don't exit prematurley 2023-04-18 18:50:54 +01:00
Alicia Sykes
ada1aebdba Also commits the README when changes made 2023-04-18 18:49:21 +01:00
Alicia Sykes
39d51898a5 Merge branch 'main' of github.com:Lissy93/portainer-templates 2023-04-18 18:46:48 +01:00
Alicia Sykes
4eea97b4e8 Updates the Makefile to update the readme 2023-04-18 18:46:39 +01:00
Liss-Bot
30b1621435 Updates templates (auto-generated, on 18-Apr-2023) 2023-04-18 17:43:01 +00:00
Alicia Sykes
9df46d7986 Writes script to generate list of apps + sources 2023-04-18 18:42:29 +01:00
Alicia Sykes
8db81dbbdd Check the line in CSV is valid, before proceeding 2023-04-18 18:42:08 +01:00
Alicia Sykes
d3fb62828d Updates the duplicate remover to remove more dupplicates 2023-04-18 18:41:39 +01:00
Alicia Sykes
1e8af535ea Updates the Makefile to check where Python bin is 2023-04-18 18:41:00 +01:00
Alicia Sykes
6ce23b0887 Updates sources listy 2023-04-18 18:39:50 +01:00
Alicia Sykes
3441cf6a64 Adds space for sources and apps list 2023-04-18 18:38:47 +01:00
Alicia Sykes
5b61f339d0 Updates the installation instructions, with screen recording 2023-04-17 23:05:22 +01:00
Alicia Sykes
9db4435782 Adds URL to readme 2023-04-17 22:42:58 +01:00
Alicia Sykes
32e97e7f62 Update README.md 2023-04-16 23:33:27 +01:00
14 changed files with 13009 additions and 9608 deletions

649
.github/README.md vendored

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,8 @@ on:
workflow_dispatch:
push:
branches: [ main ]
schedule:
- cron: '0 2 * * 0' # At 02:00 on Sunday
jobs:
build:
runs-on: ubuntu-latest
@@ -40,8 +42,14 @@ jobs:
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
git add .github/README.md
if git diff --staged --quiet; then
echo "No need to update README, skipping..."
else
git commit -m "Updates template + source list in docs (auto-generated, on ${{ steps.date.outputs.date }})"
git push
fi

89
.github/workflows/publish-docker.yml vendored Normal file
View File

@@ -0,0 +1,89 @@
# Scans, builds and releases a multi-architecture docker image
name: 🐳 Build + Publish Multi-Platform Image
on:
workflow_dispatch:
push:
branches: ['main']
tags: ['v[0-9].[0-9]+.[0-9]+']
paths:
- 'templates.json'
- 'Dockerfile'
env:
DH_IMAGE: ${{ secrets.DOCKER_REPO || github.event.repository.name }}
GH_IMAGE: ${{ github.repository_owner }}/${{ github.event.repository.name }}
jobs:
docker:
runs-on: ubuntu-latest
permissions: { contents: read, packages: write }
if: "!contains(github.event.head_commit.message, '[ci-skip]')"
steps:
- name: 🛎️ Checkout Repo
uses: actions/checkout@v2
# - name: ✨ Validate Dockerfile
# uses: ghe-actions/dockerfile-validator@v1
# with:
# dockerfile: 'Dockerfile'
# lint: 'hadolint'
- name: 🗂️ Make Docker Meta
id: meta
uses: docker/metadata-action@v3
with:
images: |
${{ env.DH_IMAGE }}
ghcr.io/${{ env.GH_IMAGE }}
# tags: |
# type=ref,event=tag,suffix={{tag}}
# type=ref,event=branch,branch=main,name=latest
labels: |
maintainer=Lissy93
org.opencontainers.image.title=Portainer-Templates
org.opencontainers.image.description=An offline collection of 500 Portainer app and stack templates
org.opencontainers.image.documentation=https://github.com/lissy93/portainer-templates
org.opencontainers.image.authors=Alicia Sykes
org.opencontainers.image.licenses=MIT
- name: 🔧 Set up QEMU
uses: docker/setup-qemu-action@v1
- name: 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: 🔑 Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: 🔑 Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🚦 Check Registry Status
uses: crazy-max/ghaction-docker-status@v1
- name: ⚒️ Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
# - name: 💬 Set Docker Hub Description
# uses: peter-evans/dockerhub-description@v2
# with:
# repository: lissy93/devolio
# readme-filepath: ./README.md
# short-description: Devolio - A developer portfolio site for the rest of us
# username: ${{ secrets.DOCKER_USERNAME }}
# password: ${{ secrets.DOCKER_USER_PASS }}

16
.github/workflows/sync-mirror.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
# Pushes the contents of the repo to the Codeberg mirror
name: 🪞 Mirror to Codeberg
on:
workflow_dispatch:
schedule:
- cron: '30 2 * * 0' # At 02:30 on Sunday
jobs:
codeberg:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with: { fetch-depth: 0 }
- uses: pixta-dev/repository-mirroring-action@v1
with:
target_repo_url: git@codeberg.org:alicia/portainer-templates.git
ssh_private_key: ${{ secrets.CODEBERG_SSH }}

View File

@@ -1,5 +1,6 @@
FROM nginx:stable-alpine
COPY templates.json /usr/share/nginx/html/templates.json
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80

View File

@@ -1,15 +1,20 @@
.PHONY: all install_requirements download combine
all: install_requirements download combine
PYTHON := $(shell which python3 2>/dev/null || which python)
all: install_requirements download combine list
install_requirements:
pip install -r lib/requirements.txt
$(PYTHON) -m pip install -r lib/requirements.txt
download:
python lib/download.py
$(PYTHON) lib/download.py
combine:
python lib/combine.py
$(PYTHON) lib/combine.py
validate:
python lib/validate.py
$(PYTHON) lib/validate.py
list:
$(PYTHON) lib/list.py

28
index.html Normal file
View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<head>
<title>Portainer Templates</title>
</head>
<body>
<main>
<h1>Portainer Templates</h1>
<p><i>Your template server is up and running 🎉</i></p>
<p>
Within your Portainer instance, you can add this URL as a template source:
<a href="/templates.json"><code>templates.json</code></a>
</p>
<p>
For further documentation, or to make changes, visit the GitHub repo at
<a href="https://github.com/lissy93/portainer-templates">github.com/lissy93/portainer-templates</a>
<br>
Or to browse the full list of apps, along with stats, config options and usage docs, see
<a href="https://portainer-templates.as93.net">portainer-templates.as93.net</a>
</p>
</main>
<style>
body { background: #101828; color: #ffffff; font-family: sans-serif; }
h1 { font-size: 3rem; text-align: center; }
main { background: #1d2939; padding: 1rem; border-radius: 6px; margin: 1rem auto; max-width: 1000px; }
i { font-size: 1.2rem; opacity: 0.8; }
a { color: #0ba5ec; font-weight: bold; }
</style>
</body>

View File

@@ -1,4 +1,5 @@
import os
import string
import json
# Get list of files in sources
@@ -13,17 +14,23 @@ 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
file_path = os.path.join(templates_src_dir, file)
if os.path.isfile(file_path) and file.endswith('.json'):
with open(file_path) as f:
# 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'])]
filtered_data = []
for x in templates:
normalized_title = x['title'].translate(str.maketrans('', '', string.punctuation)).replace(' ', '').lower()
if normalized_title not in seen_titles:
seen_titles.add(normalized_title)
filtered_data.append(x)
fileData = {
'version': '2',

View File

@@ -27,7 +27,8 @@ def get_source_list():
sources=[]
with open(sources_list, mode='r') as file:
csvFile = csv.reader(file)
for lines in csvFile:#
for lines in csvFile:
if len(lines) > 1 and lines[1].strip():
sources.append(lines)
return sources

87
lib/list.py Normal file
View File

@@ -0,0 +1,87 @@
import json
import urllib.parse
import os
import csv
import re
current_dir = os.path.dirname(os.path.abspath(__file__))
project_dir = os.path.dirname(current_dir)
readme_path = os.path.join(project_dir, '.github/README.md')
templates_path = os.path.join(project_dir, 'templates.json')
sources_path = os.path.join(project_dir, 'sources.csv')
def load_json_file(file_path):
with open(file_path, 'r') as file:
return json.load(file)
def load_csv_file(file_path):
with open(file_path, 'r') as file:
return list(csv.reader(file))
def slugify(title: str):
baseUrl = 'https://portainer-templates.as93.net'
return f'{baseUrl}/{re.sub(r"[^a-zA-Z ]", "", title.lower()).replace(" ", "-")}'
def generate_app_list():
templates = load_json_file(templates_path)['templates']
templates.sort(key=lambda template: template['title'].lower())
markdown_content = ''
for index, template in enumerate(templates):
name = template['title'].title()
description = re.sub('[^0-9a-zA-Z]+', ' ', (template['description'] or ''))
if 'logo' in template and template['logo']:
logo = f"<img title=\"{description}\" src='{template['logo']}' width='26' height='26' /> "
else:
logo = ' '
markdown_content += f"{index+1}. {logo}**[{name}]({slugify(name)} '{description}')**\n"
return markdown_content
def generate_sources_list():
sources = load_csv_file(sources_path)
markdown_content = ''
for index, source in enumerate(sources):
if len(source) > 1 and source[1].strip():
url = source[1].strip()
parsed_url = urllib.parse.urlparse(url)
username = parsed_url.path.split('/')[1]
avatar = f'<img src="https://github.com/{username}.png?size=40" width="26" height="26" />'
markdown_content += f"{index + 1}. {avatar} [template]({url}) by [@{username}](https://github.com/{username})\n"
return markdown_content
def insert_content_between_markers(file_path, start_marker, end_marker, content_to_insert):
with open(file_path, 'r') as file:
lines = file.readlines()
start_index = -1
end_index = -1
for i, line in enumerate(lines):
if start_marker in line:
start_index = i
if end_marker in line:
end_index = i
break
if start_index >= 0 and end_index >= 0:
lines[start_index + 1:end_index] = [content_to_insert + '\n']
with open(file_path, 'w') as file:
file.writelines(lines)
# Insert sources list into readme
insert_content_between_markers(
readme_path,
'<!-- auto-insert-sources:start -->',
'<!-- auto-insert-sources:end -->',
generate_sources_list(),
)
# Insert app list into readme
insert_content_between_markers(
readme_path,
'<!-- auto-insert-apps:start -->',
'<!-- auto-insert-apps:end -->',
generate_app_list(),
)

View File

@@ -4,3 +4,9 @@ selfhostedpro_templates, https://raw.githubusercontent.com/SelfhostedPro/selfhos
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
novaspirit_templates, https://raw.githubusercontent.com/novaspirit/pi-hosted/master/pi-hosted_template/template/portainer-v2.json
donpablonow_templates, https://raw.githubusercontent.com/donpablonow/awesome-saas/master/Template/portainer-v2.json
mediadepot_templates, https://raw.githubusercontent.com/mediadepot/templates/master/portainer.json
mycroftwilde_templates, https://raw.githubusercontent.com/mycroftwilde/portainer_templates/master/Template/template.json
mediadepot_templates, https://raw.githubusercontent.com/mediadepot/templates/master/portainer.json
portainer_templates, https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json
1 dnburgess_templates https://raw.githubusercontent.com/dnburgess/self-hosted-template/master/template.json
4 technorabilia_templates https://raw.githubusercontent.com/technorabilia/portainer-templates/main/lsio/templates/templates-2.0.json
5 mikestraney_templates https://raw.githubusercontent.com/mikestraney/portainer-templates/master/templates.json
6 xneo1_templates https://raw.githubusercontent.com/xneo1/portainer_templates/master/Template/template.json
7 novaspirit_templates https://raw.githubusercontent.com/novaspirit/pi-hosted/master/pi-hosted_template/template/portainer-v2.json
8 donpablonow_templates https://raw.githubusercontent.com/donpablonow/awesome-saas/master/Template/portainer-v2.json
9 mediadepot_templates https://raw.githubusercontent.com/mediadepot/templates/master/portainer.json
10 mycroftwilde_templates https://raw.githubusercontent.com/mycroftwilde/portainer_templates/master/Template/template.json
11 mediadepot_templates https://raw.githubusercontent.com/mediadepot/templates/master/portainer.json
12 portainer_templates https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json

View File

@@ -0,0 +1,205 @@
{
"version": "2",
"templates": [
{
"categories": [
"Productivity",
"Social"
],
"description": "Open source collaborative knowledge base for modern teams",
"env": [
{
"default": "production",
"label": "NODE_ENV",
"name": "NODE_ENV"
},
{
"default": "",
"label": "SECRET_KEY",
"name": "SECRET_KEY"
},
{
"default": "",
"label": "UTILS_SECRET",
"name": "UTILS_SECRET"
},
{
"default": "",
"label": "DATABASE_URL",
"name": "DATABASE_URL"
},
{
"default": "",
"label": "DATABASE_URL_TEST",
"name": "DATABASE_URL_TEST"
},
{
"default": "",
"label": "DATABASE_CONNECTION_POOL_MIN",
"name": "DATABASE_CONNECTION_POOL_MIN"
},
{
"default": "",
"label": "DATABASE_CONNECTION_POOL_MAX",
"name": "DATABASE_CONNECTION_POOL_MAX"
},
{
"default": "",
"label": "REDIS_URL",
"name": "REDIS_URL"
},
{
"default": "",
"label": "URL",
"name": "URL"
},
{
"default": "3000",
"label": "PORT",
"name": "PORT"
},
{
"default": "",
"label": "COLLABORATION_URL",
"name": "COLLABORATION_URL"
},
{
"default": "",
"label": "GOOGLE_CLIENT_ID",
"name": "GOOGLE_CLIENT_ID"
},
{
"default": "",
"label": "GOOGLE_CLIENT_SECRET",
"name": "GOOGLE_CLIENT_SECRET"
},
{
"default": "",
"label": "SSL_KEY",
"name": "SSL_KEY"
},
{
"default": "",
"label": "SSL_CERT",
"name": "SSL_CERT"
},
{
"default": "true",
"label": "FORCE_HTTPS",
"name": "FORCE_HTTPS"
},
{
"default": "true",
"label": "ENABLE_UPDATES",
"name": "ENABLE_UPDATES"
},
{
"default": "1",
"label": "WEB_CONCURRENCY",
"name": "WEB_CONCURRENCY"
},
{
"default": "5120000",
"label": "MAXIMUM_IMPORT_SIZE",
"name": "MAXIMUM_IMPORT_SIZE"
},
{
"default": "http",
"label": "DEBUG",
"name": "DEBUG"
},
{
"default": "info",
"label": "LOG_LEVEL",
"name": "LOG_LEVEL"
},
{
"default": "",
"label": "GOOGLE_ANALYTICS_ID",
"name": "GOOGLE_ANALYTICS_ID"
},
{
"default": "",
"label": "SENTRY_DSN",
"name": "SENTRY_DSN"
},
{
"default": "",
"label": "SENTRY_TUNNEL",
"name": "SENTRY_TUNNEL"
},
{
"default": "",
"label": "SMTP_HOST",
"name": "SMTP_HOST"
},
{
"default": "",
"label": "SMTP_PORT",
"name": "SMTP_PORT"
},
{
"default": "",
"label": "SMTP_USERNAME",
"name": "SMTP_USERNAME"
},
{
"default": "",
"label": "SMTP_PASSWORD",
"name": "SMTP_PASSWORD"
},
{
"default": "",
"label": "SMTP_FROM_EMAIL",
"name": "SMTP_FROM_EMAIL"
},
{
"default": "",
"label": "SMTP_REPLY_EMAIL",
"name": "SMTP_REPLY_EMAIL"
},
{
"default": "",
"label": "SMTP_TLS_CIPHERS",
"name": "SMTP_TLS_CIPHERS"
},
{
"default": "true",
"label": "SMTP_SECURE",
"name": "SMTP_SECURE"
},
{
"default": "en_US",
"label": "DEFAULT_LANGUAGE",
"name": "DEFAULT_LANGUAGE"
},
{
"default": "true",
"label": "RATE_LIMITER_ENABLED",
"name": "RATE_LIMITER_ENABLED"
},
{
"default": "1000",
"label": "RATE_LIMITER_REQUESTS",
"name": "RATE_LIMITER_REQUESTS"
},
{
"default": "60",
"label": "RATE_LIMITER_DURATION_WINDOW",
"name": "RATE_LIMITER_DURATION_WINDOW"
}
],
"logo": "https://avatars.githubusercontent.com/u/1765001",
"name": "outline",
"note": "Open source collaborative knowledge base for modern teams",
"platform": "linux",
"repository": {
"stackfile": "sources/stacks/outline.yml",
"url": "https://github.com/lissy93/portainer-templates"
},
"restart_policy": "unless-stopped",
"title": "Outline",
"type": 3
}
]
}

View File

@@ -0,0 +1,88 @@
version: "3"
services:
outline:
image: docker.getoutline.com/outlinewiki/outline:latest
env_file: ./docker.env
ports:
- "3000:3000"
depends_on:
- postgres
- redis
- storage
redis:
image: redis
env_file: ./docker.env
ports:
- "6379:6379"
volumes:
- ./redis.conf:/redis.conf
command: ["redis-server", "/redis.conf"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 30s
retries: 3
postgres:
image: postgres
env_file: ./docker.env
ports:
- "5432:5432"
volumes:
- database-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready"]
interval: 30s
timeout: 20s
retries: 3
environment:
POSTGRES_USER: 'user'
POSTGRES_PASSWORD: 'pass'
POSTGRES_DB: 'outline'
storage:
image: minio/minio
env_file: ./docker.env
ports:
- "9000:9000"
entrypoint: sh
command: -c 'minio server'
deploy:
restart_policy:
condition: on-failure
volumes:
- storage-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
https-portal:
image: steveltn/https-portal
env_file: ./docker.env
ports:
- '80:80'
- '443:443'
links:
- outline
- storage
restart: always
volumes:
- https-portal-data:/var/lib/https-portal
healthcheck:
test: ["CMD", "service", "nginx", "status"]
interval: 30s
timeout: 20s
retries: 3
environment:
DOMAINS: 'docs.mycompany.com -> http://outline:3000'
STAGE: 'production'
WEBSOCKET: 'true'
volumes:
https-portal-data:
storage-data:
database-data:

File diff suppressed because it is too large Load Diff