Compare commits

...

25 Commits

Author SHA1 Message Date
Lee
b6bd431c40 oops
All checks were successful
Publish Docker Image / docker (push) Successful in 1m32s
2025-02-07 23:00:02 +00:00
Lee
da1030c960 Merge branch 'master' of https://git.fascinated.cc/Fascinated/traefik-helper
All checks were successful
Publish Docker Image / docker (push) Successful in 3m59s
2025-02-07 22:12:12 +00:00
Lee
209536614e add catch all 2025-02-07 22:12:01 +00:00
Lee
89da5d6c0d Update src/command/impl/removeCommand.py
All checks were successful
Publish Docker Image / docker (push) Successful in 2m27s
2024-09-14 23:36:29 +00:00
019261a988 fixes
All checks were successful
Publish Docker Image / docker (push) Successful in 1m21s
2024-08-28 03:01:48 +01:00
7d861aad76 fixes
All checks were successful
Publish Docker Image / docker (push) Successful in 1m32s
2024-08-28 02:57:25 +01:00
6430dc5bc4 fixes
All checks were successful
Publish Docker Image / docker (push) Successful in 58s
2024-08-28 02:53:53 +01:00
304451ef7c fixes
All checks were successful
Publish Docker Image / docker (push) Successful in 1m9s
2024-08-28 02:46:46 +01:00
ee7a0b7f63 fix
All checks were successful
Publish Docker Image / docker (push) Successful in 58s
2024-08-28 02:42:37 +01:00
a1ec2c1602 oopsie doodle
All checks were successful
Publish Docker Image / docker (push) Successful in 1m4s
2024-08-28 02:38:17 +01:00
71b55d5d17 skull emoji
All checks were successful
Publish Docker Image / docker (push) Successful in 1m34s
2024-08-28 02:35:49 +01:00
30e3d3363c maybe add sub path support
Some checks failed
Publish Docker Image / docker (push) Failing after 1m34s
2024-08-28 02:33:32 +01:00
97ac22e62e update readme 2024-04-17 02:41:34 +01:00
35ef584cd7 update readme 2024-04-17 02:40:42 +01:00
f3599cc4ac add tail to not spam
All checks were successful
Publish Docker Image / docker (push) Successful in 1m15s
2024-04-17 02:39:25 +01:00
2c0d4cdcae add logs command
All checks were successful
Publish Docker Image / docker (push) Successful in 1m30s
2024-04-17 02:36:38 +01:00
9ca94d0e05 fix missing usage
All checks were successful
Publish Docker Image / docker (push) Successful in 1m5s
2024-04-17 02:31:19 +01:00
cacdf1f5b9 add restart command
All checks were successful
Publish Docker Image / docker (push) Successful in 2m53s
2024-04-17 02:24:45 +01:00
Lee
4ee7337e9d Upload files to "/"
All checks were successful
Publish Docker Image / docker (push) Successful in 1m17s
2024-01-15 23:54:36 +00:00
d37c414466 validate the service host
All checks were successful
Publish Docker Image / docker (push) Successful in 1m10s
2024-01-15 23:15:54 +00:00
e65d84c915 Merge branch 'master' of https://git.fascinated.cc/Fascinated/traefik-helper
Some checks failed
Publish Docker Image / docker (push) Has been cancelled
2024-01-15 23:14:47 +00:00
deb7f4fc5a print url of service 2024-01-15 23:14:45 +00:00
Lee
c00432b425 Update README.md 2024-01-15 23:09:41 +00:00
669a371c0d cleanup
All checks were successful
Publish Docker Image / docker (push) Successful in 1m17s
2024-01-15 23:09:08 +00:00
4ba7eec661 meow
All checks were successful
Publish Docker Image / docker (push) Successful in 1m11s
2024-01-15 23:00:26 +00:00
14 changed files with 221 additions and 27 deletions

View File

@ -4,7 +4,7 @@ FROM python:3.10-slim AS builder
# Install Docker # Install Docker
RUN apt update RUN apt update
RUN apt install curl -y RUN apt install curl -y
RUN curl -sSL https://s.fascinated.cc/s/install-docker | bash RUN curl -sSL https://get.docker.com/ | CHANNEL=stable bash
# Step 2: Create the final image # Step 2: Create the final image
FROM python:3.10-slim FROM python:3.10-slim

9
LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2023 Fascinated
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -4,7 +4,8 @@ This is a helper container for traefik. It can add, remove and update services.
## NOTICE ## NOTICE
PLEASE PLEASE PLEASE MAKE SURE YOU HAVE A BACKUP OF YOUR CONFIG FILE BEFORE USING THIS CONTAINER. I AM NOT RESPONSIBLE FOR ANY DATA LOSS. PLEASE PLEASE PLEASE MAKE SURE YOU HAVE A BACKUP OF YOUR CONFIG FILE BEFORE USING THIS CONTAINER. I AM NOT RESPONSIBLE FOR ANY DATA LOSS. </br>
This helper also assumes that you have SSL certificates setup for your services.
## Usage ## Usage
@ -22,6 +23,10 @@ traefik-helper
## Windows Alias ## Windows Alias
Ensure you have ran `Set-ExecutionPolicy Unrestricted` in PowerShell as an administrator.
Create the directory `~/Documents/WindowsPowerShell` and create a file called `Microsoft.PowerShell_profile.ps1` in that directory. Add the following code to the file.
```bash ```bash
function Traefik-Helper { function Traefik-Helper {
$argsAsString = $args -join ' ' $argsAsString = $args -join ' '
@ -34,3 +39,5 @@ function Traefik-Helper {
# Set the alias # Set the alias
Set-Alias -Name "traefik" -Value "Traefik-Helper" Set-Alias -Name "traefik" -Value "Traefik-Helper"
``` ```
This will allow you to run the `traefik` command in PowerShell.

View File

@ -1,6 +1,10 @@
from command.impl.addCommand import AddCommand from command.impl.addCommand import AddCommand
from command.impl.listCommand import ListCommand from command.impl.listCommand import ListCommand
from command.impl.removeCommand import RemoveCommand from command.impl.removeCommand import RemoveCommand
from command.impl.restartCommand import RestartCommand
from command.impl.logsCommand import LogsCommand
from command.impl.addSubPathCommand import AddSubPathCommand
from command.impl.addCatchAllCommand import AddCatchAllCommand
class CommandManager: class CommandManager:
@ -10,8 +14,13 @@ class CommandManager:
self.addCommand(AddCommand()) self.addCommand(AddCommand())
self.addCommand(RemoveCommand()) self.addCommand(RemoveCommand())
self.addCommand(ListCommand()) self.addCommand(ListCommand())
self.addCommand(RestartCommand())
self.addCommand(LogsCommand())
self.addCommand(AddSubPathCommand())
self.addCommand(AddCatchAllCommand())
pass pass
def addCommand(self, command): def addCommand(self, command):
self.commands.append(command) self.commands.append(command)
pass pass

View File

@ -0,0 +1,32 @@
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class AddCatchAllCommand(Command):
def __init__(self):
super().__init__("add-catch-all", "Add a catch all domain", "add-catch-all <name> <domain> <service host>")
def execute(self, traefikConfig: TraefikConfig, args):
if len(args) < 3:
self.printUsage()
return
name = args[0]
domain = args[1]
serviceHost = args[2]
if traefikConfig.hasRouter(name):
print(f"Router \"{name}\" already exists")
return
# Validate if the service host is a valid URL
if not serviceHost.startswith("http://") and not serviceHost.startswith("https://"):
print(f"Service host \"{serviceHost}\" is not a valid URL")
return
print(f"Adding \"{domain}\" -> \"{serviceHost}\"")
traefikConfig.addCatchAllRouter(name, domain, serviceHost)
traefikConfig.save()
print(f"Access your service at http://{domain}")

View File

@ -6,7 +6,7 @@ class AddCommand(Command):
def __init__(self): def __init__(self):
super().__init__("add", "Add a domain", "add <name> <domain> <service host>") super().__init__("add", "Add a domain", "add <name> <domain> <service host>")
def execute(self, traefikConfig:TraefikConfig, args): def execute(self, traefikConfig: TraefikConfig, args):
if len(args) < 3: if len(args) < 3:
self.printUsage() self.printUsage()
return return
@ -19,13 +19,14 @@ class AddCommand(Command):
print(f"Router \"{name}\" already exists") print(f"Router \"{name}\" already exists")
return return
# Validate if the service host is a valid URL
if not serviceHost.startswith("http://") and not serviceHost.startswith("https://"):
print(f"Service host \"{serviceHost}\" is not a valid URL")
return
print(f"Adding \"{domain}\" -> \"{serviceHost}\"") print(f"Adding \"{domain}\" -> \"{serviceHost}\"")
traefikConfig.addRouter(name, domain, serviceHost) traefikConfig.addRouter(name, domain, serviceHost)
traefikConfig.addService(name, serviceHost)
traefikConfig.save() traefikConfig.save()
restartTraefik() print(f"Access your service at http://{domain}")
print("Done!")

View File

@ -0,0 +1,43 @@
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class AddSubPathCommand(Command):
def __init__(self):
super().__init__("add-path", "Add sub path to a domain (eg: bob.com/joe)", "add-path <name> <domain> <path> <service host>")
def execute(self, traefikConfig: TraefikConfig, args):
if len(args) < 3:
self.printUsage()
return
router = args[0]
domain = args[1]
path = args[2]
# Fix the path
if path.startswith("/") == False:
path = "/" + path
if path.endswith("/") == True:
path = path[:-1] # Remove the trailing slash
serviceHost = args[3]
subPathName = domain + path
if traefikConfig.hasPathRewrite(subPathName):
print(f"Sub path for \"{domain}{path}\" already exists")
return
if traefikConfig.hasRouter(router) == False:
print(f"Router \"{router}\" does not exist")
return
# Validate if the service host is a valid URL
if not serviceHost.startswith("http://") and not serviceHost.startswith("https://"):
print(f"Service host \"{serviceHost}\" is not a valid URL")
return
print(f"Adding \"{domain}{path}\" -> \"{serviceHost}\"")
traefikConfig.addSubPathRouter(subPathName, domain, path, serviceHost)
traefikConfig.save()
print(f"Access your service at http://{domain}{path}")

View File

@ -6,7 +6,7 @@ class ListCommand(Command):
def __init__(self): def __init__(self):
super().__init__("list", "List all services", "list") super().__init__("list", "List all services", "list")
def execute(self, traefikConfig:TraefikConfig, args): def execute(self, traefikConfig: TraefikConfig, args):
print("Listing all services:") print("Listing all services:")
domains = traefikConfig.getAll() domains = traefikConfig.getAll()

View File

@ -0,0 +1,10 @@
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import getTraefikLogs
class LogsCommand(Command):
def __init__(self):
super().__init__("logs", "Get traefik logs", "logs")
def execute(self, traefikConfig: TraefikConfig, args):
getTraefikLogs()

View File

@ -1,13 +1,12 @@
from colorama import Fore from colorama import Fore
from command.command import Command from command.command import Command
from traefik.traefikConfig import TraefikConfig from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class RemoveCommand(Command): class RemoveCommand(Command):
def __init__(self): def __init__(self):
super().__init__("remove", "Remove a domain", "remove <name>") super().__init__("remove", "Remove a domain", "remove <name>")
def execute(self, traefikConfig:TraefikConfig, args): def execute(self, traefikConfig: TraefikConfig, args):
if len(args) < 0: if len(args) < 0:
self.printUsage() self.printUsage()
return return
@ -23,7 +22,3 @@ class RemoveCommand(Command):
traefikConfig.removeRouter(name) traefikConfig.removeRouter(name)
traefikConfig.save() traefikConfig.save()
restartTraefik()
print(f"Removed \"{name}\"")

View File

@ -0,0 +1,27 @@
from colorama import Fore
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class RemoveCommand(Command):
def __init__(self):
super().__init__("remove-sub-path", "Remove sub path from a domain", "remove-sub-path <name> <path>")
def execute(self, traefikConfig: TraefikConfig, args):
if len(args) < 0:
self.printUsage()
return
name = args[0]
if not traefikConfig.hasRouter(name):
print(f"Router \"{name}\" does not exist")
return
print(f"Removing \"{name}\"")
traefikConfig.removeRouter(name)
traefikConfig.save()
restartTraefik()

View File

@ -0,0 +1,10 @@
from command.command import Command
from traefik.traefikConfig import TraefikConfig
from utils.dockerUtils import restartTraefik
class RestartCommand(Command):
def __init__(self):
super().__init__("restart", "Restart traefik", "restart")
def execute(self, traefikConfig: TraefikConfig, args):
restartTraefik()

View File

@ -38,17 +38,17 @@ class TraefikConfig:
} }
} }
def removeRouter(self, name): def addCatchAllRouter(self, name, domain, serviceHost):
# Remove router # Add router
del self.configYml["http"]["routers"][name] self.configYml["http"]["routers"][name] = {
"entryPoints": ["https"],
"rule": "HostRegexp(`{subdomain:[A-Za-z0-9-]+}.%s`)" % domain,
"middlewares": ["default-headers", "https-redirectscheme"],
"tls": {},
"priority": 1,
"service": name
}
# Remove service
del self.configYml["http"]["services"][name]
def hasRouter(self, name):
return name in self.configYml["http"]["routers"]
def addService(self, name, serviceHost):
# Add service # Add service
self.configYml["http"]["services"][name] = { self.configYml["http"]["services"][name] = {
"loadBalancer": { "loadBalancer": {
@ -60,6 +60,53 @@ class TraefikConfig:
} }
} }
def addSubPathRouter(self, name, domain, path, serviceHost):
# Add trailing slashs
if not path.endswith("/"):
path += "/"
if not serviceHost.endswith("/"):
serviceHost += "/"
# Add path stripper middleware
self.configYml["http"]["middlewares"][name] = {
"stripPrefix": {
"prefixes": [path]
}
}
# Add router
self.configYml["http"]["routers"][name] = {
"entryPoints": ["https"],
"rule": "Host(`%s`) && PathPrefix(`%s`)" % (domain, path),
"middlewares": ["default-headers", "https-redirectscheme", name],
"tls": {},
"service": name
}
# Add service
self.configYml["http"]["services"][name] = {
"loadBalancer": {
"servers": [
{
"url": serviceHost
}
]
}
}
def removeRouter(self, name):
# Remove router
del self.configYml["http"]["routers"][name]
# Remove service
del self.configYml["http"]["services"][name]
def hasRouter(self, name):
return name in self.configYml["http"]["routers"]
def hasPathRewrite(self, name):
return name in self.configYml["http"]["middlewares"]
def hasService(self, name): def hasService(self, name):
return name in self.configYml["http"]["services"] return name in self.configYml["http"]["services"]

View File

@ -16,3 +16,7 @@ def restartTraefik():
subprocess.run(["docker", "restart", containerName]) subprocess.run(["docker", "restart", containerName])
print("Done!") print("Done!")
def getTraefikLogs():
print("Getting Traefik logs, please wait...")
subprocess.run(["docker", "logs", containerName, "-f", "--tail=250"])