fujin-cli 0.5.0__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fujin-cli might be problematic. Click here for more details.
- fujin/commands/init.py +0 -2
- fujin/config.py +7 -6
- fujin/proxies/nginx.py +14 -16
- {fujin_cli-0.5.0.dist-info → fujin_cli-0.6.0.dist-info}/METADATA +8 -5
- {fujin_cli-0.5.0.dist-info → fujin_cli-0.6.0.dist-info}/RECORD +8 -8
- {fujin_cli-0.5.0.dist-info → fujin_cli-0.6.0.dist-info}/WHEEL +1 -1
- {fujin_cli-0.5.0.dist-info → fujin_cli-0.6.0.dist-info}/entry_points.txt +0 -0
- {fujin_cli-0.5.0.dist-info → fujin_cli-0.6.0.dist-info}/licenses/LICENSE.txt +0 -0
fujin/commands/init.py
CHANGED
|
@@ -54,7 +54,6 @@ def simple_config(app_name) -> dict:
|
|
|
54
54
|
},
|
|
55
55
|
"aliases": {"shell": "server exec --appenv -i bash"},
|
|
56
56
|
"host": {
|
|
57
|
-
"ip": "127.0.0.1",
|
|
58
57
|
"user": "root",
|
|
59
58
|
"domain_name": f"{app_name}.com",
|
|
60
59
|
"envfile": ".env.prod",
|
|
@@ -111,7 +110,6 @@ def binary_config(app_name: str) -> dict:
|
|
|
111
110
|
"processes": {"web": f"{app_name} prodserver"},
|
|
112
111
|
"aliases": {"shell": "server exec --appenv -i bash"},
|
|
113
112
|
"host": {
|
|
114
|
-
"ip": "127.0.0.1",
|
|
115
113
|
"user": "root",
|
|
116
114
|
"domain_name": f"{app_name}.com",
|
|
117
115
|
"envfile": ".env.prod",
|
fujin/config.py
CHANGED
|
@@ -14,6 +14,10 @@ python_version
|
|
|
14
14
|
The Python version for your virtualenv. If not specified, automatically parsed from ``.python-version`` file. This is only
|
|
15
15
|
required if the installation mode is set to ``python-package``
|
|
16
16
|
|
|
17
|
+
requirements
|
|
18
|
+
------------
|
|
19
|
+
Optional path to your requirements file. This will only be used when the installation mode is set to ``python-package``
|
|
20
|
+
|
|
17
21
|
versions_to_keep
|
|
18
22
|
----------------
|
|
19
23
|
The number of versions to keep on the host. After each deploy, older versions are pruned based on this setting. By default, it keeps the latest 5 versions,
|
|
@@ -39,10 +43,6 @@ release_command
|
|
|
39
43
|
---------------
|
|
40
44
|
Optional command to run at the end of deployment (e.g., database migrations).
|
|
41
45
|
|
|
42
|
-
requirements
|
|
43
|
-
------------
|
|
44
|
-
Optional path to your requirements file. This will only be used when the installation mode is set to ``python-package``
|
|
45
|
-
|
|
46
46
|
Webserver
|
|
47
47
|
---------
|
|
48
48
|
|
|
@@ -101,7 +101,7 @@ Host Configuration
|
|
|
101
101
|
|
|
102
102
|
ip
|
|
103
103
|
~~
|
|
104
|
-
The IP address or
|
|
104
|
+
The IP address or anything that resolves to the remote host IP's. This is use to communicate via ssh with the server, if omitted it's value will default to the one of the ``domain_name``.
|
|
105
105
|
|
|
106
106
|
domain_name
|
|
107
107
|
~~~~~~~~~~~
|
|
@@ -234,7 +234,7 @@ class Config(msgspec.Struct, kw_only=True):
|
|
|
234
234
|
|
|
235
235
|
|
|
236
236
|
class HostConfig(msgspec.Struct, kw_only=True):
|
|
237
|
-
ip: str
|
|
237
|
+
ip: str | None = None
|
|
238
238
|
domain_name: str
|
|
239
239
|
user: str
|
|
240
240
|
_envfile: str = msgspec.field(name="envfile")
|
|
@@ -245,6 +245,7 @@ class HostConfig(msgspec.Struct, kw_only=True):
|
|
|
245
245
|
|
|
246
246
|
def __post_init__(self):
|
|
247
247
|
self.apps_dir = f"/home/{self.user}/{self.apps_dir}"
|
|
248
|
+
self.ip = self.ip or self.domain_name
|
|
248
249
|
|
|
249
250
|
def to_dict(self):
|
|
250
251
|
d = {f: getattr(self, f) for f in self.__struct_fields__}
|
fujin/proxies/nginx.py
CHANGED
|
@@ -35,20 +35,20 @@ class WebProxy(msgspec.Struct):
|
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
def run_pty(self, *args, **kwargs):
|
|
38
|
-
return self.
|
|
38
|
+
return self.run_pty(*args, **kwargs, pty=True)
|
|
39
39
|
|
|
40
40
|
def install(self):
|
|
41
|
-
self.
|
|
41
|
+
self.run_pty(
|
|
42
42
|
"sudo apt install -y nginx libpq-dev python3-dev python3-certbot-nginx"
|
|
43
43
|
)
|
|
44
44
|
|
|
45
45
|
def uninstall(self):
|
|
46
46
|
self.stop()
|
|
47
|
-
self.
|
|
48
|
-
self.
|
|
49
|
-
self.
|
|
50
|
-
self.
|
|
51
|
-
self.
|
|
47
|
+
self.run_pty("sudo apt remove -y nginx")
|
|
48
|
+
self.run_pty(f"sudo rm /etc/nginx/sites-available/{self.app_name}.conf")
|
|
49
|
+
self.run_pty(f"sudo rm /etc/nginx/sites-enabled/{self.app_name}.conf")
|
|
50
|
+
self.run_pty("sudo systemctl disable certbot.timer")
|
|
51
|
+
self.run_pty("sudo apt remove -y python3-certbot-nginx")
|
|
52
52
|
|
|
53
53
|
def setup(self):
|
|
54
54
|
conf = (
|
|
@@ -65,11 +65,11 @@ class WebProxy(msgspec.Struct):
|
|
|
65
65
|
)
|
|
66
66
|
if CERTBOT_EMAIL:
|
|
67
67
|
cert_path = f"/etc/letsencrypt/live/{self.domain_name}/fullchain.pem"
|
|
68
|
-
cert_exists = self.
|
|
68
|
+
cert_exists = self.run_pty(f"sudo test -f {cert_path}", warn=True).ok
|
|
69
69
|
|
|
70
70
|
if not cert_exists:
|
|
71
|
-
self.
|
|
72
|
-
f"certbot --nginx -d {self.domain_name} --non-interactive --agree-tos --email {CERTBOT_EMAIL} --redirect"
|
|
71
|
+
self.run_pty(
|
|
72
|
+
f"sudo certbot --nginx -d {self.domain_name} --non-interactive --agree-tos --email {CERTBOT_EMAIL} --redirect"
|
|
73
73
|
)
|
|
74
74
|
self.config_file.parent.mkdir(exist_ok=True)
|
|
75
75
|
self.conn.get(
|
|
@@ -83,9 +83,7 @@ class WebProxy(msgspec.Struct):
|
|
|
83
83
|
def teardown(self):
|
|
84
84
|
self.run_pty(f"sudo rm /etc/nginx/sites-available/{self.app_name}.conf")
|
|
85
85
|
self.run_pty(f"sudo rm /etc/nginx/sites-enabled/{self.app_name}.conf")
|
|
86
|
-
self.run_pty(
|
|
87
|
-
"sudo systemctl restart nginx",
|
|
88
|
-
)
|
|
86
|
+
self.run_pty("sudo systemctl restart nginx")
|
|
89
87
|
|
|
90
88
|
def start(self) -> None:
|
|
91
89
|
self.run_pty("sudo systemctl start nginx")
|
|
@@ -109,9 +107,9 @@ class WebProxy(msgspec.Struct):
|
|
|
109
107
|
static_locations = ""
|
|
110
108
|
for path, directory in self.statics.items():
|
|
111
109
|
static_locations += f"""
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
location {path} {{
|
|
111
|
+
alias {directory};
|
|
112
|
+
}}
|
|
115
113
|
"""
|
|
116
114
|
|
|
117
115
|
return f"""
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: fujin-cli
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Get your project up and running in a few minutes on your own vps.
|
|
5
5
|
Project-URL: Documentation, https://github.com/falcopackages/fujin#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/falcopackages/fujin/issues
|
|
7
7
|
Project-URL: Source, https://github.com/falcopackages/fujin
|
|
8
8
|
Author-email: Tobi DEGNON <tobidegnon@proton.me>
|
|
9
|
-
License-File: LICENSE.txt
|
|
10
9
|
Keywords: caddy,deployment,django,fastapi,litestar,python,systemd
|
|
11
10
|
Classifier: Development Status :: 3 - Alpha
|
|
12
11
|
Classifier: Intended Audience :: Developers
|
|
@@ -37,16 +36,18 @@ Description-Content-Type: text/markdown
|
|
|
37
36
|
> [!IMPORTANT]
|
|
38
37
|
> This package currently contains minimal features and is a work-in-progress
|
|
39
38
|
|
|
39
|
+
<!-- content:start -->
|
|
40
|
+
|
|
40
41
|
`fujin` is a simple deployment tool that helps you get your project up and running on a VPS in a few minutes. It manages your app processes using `systemd` and runs your apps behind [caddy](https://caddyserver.com/). For Python projects,
|
|
41
42
|
it expects your app to be a packaged Python application ideally with a CLI entry point defined. For other languages, you need to provide a self-contained single executable file with all necessary dependencies.
|
|
42
43
|
The main job of `fujin` is to bootstrap your server (installing caddy, etc.), copy the files onto the server with a structure that supports rollback, and automatically generate configs for systemd and caddy that you can manually edit if needed.
|
|
43
44
|
|
|
44
|
-
Check out the [documentation📚](https://fujin.
|
|
45
|
+
Check out the [documentation📚](https://fujin.oluwatobi.dev/en/latest/) for installation, features, and usage guides.
|
|
45
46
|
|
|
46
47
|
## Why?
|
|
47
48
|
|
|
48
49
|
I wanted [kamal](https://kamal-deploy.org/) but without Docker, and I thought the idea was fun. At its core, this project automates versions of this [tutorial](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu). If you've been a Django beginner
|
|
49
|
-
trying to get your app in production, you probably went through this. I'm using caddy instead of nginx because
|
|
50
|
+
trying to get your app in production, you probably went through this. I'm using caddy instead of nginx because it's configurable via an API and it's is a no-brainer for SSL certificates. Systemd is the default on most Linux distributions and does a good enough job.
|
|
50
51
|
|
|
51
52
|
Fujin was initially planned to be a Python-only project, but the core concepts can be applied to any language that can produce a single distributable file (e.g., Go, Rust). I wanted to recreate kamal's nice local-to-remote app management API, but I'm skipping Docker to keep things simple.
|
|
52
53
|
I'm currently rocking SQLite in production for my side projects and ths setup is enough for my use case.
|
|
@@ -64,3 +65,5 @@ Fujin draws inspiration from the following tools for their developer experience.
|
|
|
64
65
|
## License
|
|
65
66
|
|
|
66
67
|
`fujin` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
|
68
|
+
|
|
69
|
+
<!-- content:end -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
fujin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
fujin/__main__.py,sha256=St0VnEWhRRw_ukAddAwDGFliLqQT3xlone-9JIONlDI,1702
|
|
3
|
-
fujin/config.py,sha256=
|
|
3
|
+
fujin/config.py,sha256=GecU6XklYNXjjR7bkRORBcX1-AYlIaTMw1mmYKSCSnA,9595
|
|
4
4
|
fujin/connection.py,sha256=ZkYaNykRFj9Yr-K-vOrZtVVGUDurDm6W7OQrgct71CA,2428
|
|
5
5
|
fujin/errors.py,sha256=74Rh-Sgql1YspPdR_akQ2G3xZ48zecyafYCptpaFo1A,73
|
|
6
6
|
fujin/hooks.py,sha256=QHIqxLxujG2U70UkN1BpUplE6tTqn7pFJP5oHde1tUQ,1350
|
|
@@ -11,7 +11,7 @@ fujin/commands/config.py,sha256=xdfd1OZLxw2YZldiAbW5rq5EBXEaXbUC-I7FKLRfzIQ,2387
|
|
|
11
11
|
fujin/commands/deploy.py,sha256=oAOLUrtHjHkmIA3D0AiaJRWEsfVk51_I29kRC_FhjYo,5463
|
|
12
12
|
fujin/commands/docs.py,sha256=b5FZ8AgoAfn4q4BueEQvM2w5HCuh8-rwBqv_CRFVU8E,349
|
|
13
13
|
fujin/commands/down.py,sha256=v1lAq70ApktjeHRB_1sCzjmKH8t6EXqyL4RTt7OE-f0,1716
|
|
14
|
-
fujin/commands/init.py,sha256=
|
|
14
|
+
fujin/commands/init.py,sha256=t8uwwOi4SBqHjV8px_SkTHAeZIiIUJnFN-lf7DK6HhE,3959
|
|
15
15
|
fujin/commands/proxy.py,sha256=ajXwboS0gDDiMWW7b9rtWU6WPF1h7JYYeycDyU-hQfg,3053
|
|
16
16
|
fujin/commands/prune.py,sha256=C2aAN6AUS84jgRg1eiCroyiuZyaZDmf5yvGAQY9xkcg,1517
|
|
17
17
|
fujin/commands/redeploy.py,sha256=JvCJBZBcCKkUw1efZwRPJMLUAV8oqBAZeSbUBLHyn3k,2185
|
|
@@ -24,12 +24,12 @@ fujin/process_managers/systemd.py,sha256=qG_4Ew8SEWtaTFOAW_XZXsMO2WjFWZ4dp5nBwAP
|
|
|
24
24
|
fujin/proxies/__init__.py,sha256=UuWYU175tkdaz1WWRCDDpQgGfFVYYNR9PBxA3lTCNr0,695
|
|
25
25
|
fujin/proxies/caddy.py,sha256=dzLD8s664_kIK-1hCE3y50JIwBd8kK9yS1LynUDRVSE,7908
|
|
26
26
|
fujin/proxies/dummy.py,sha256=qBKSn8XNEA9SVwB7GzRNX2l9Iw6tUjo2CFqZjWi0FjY,465
|
|
27
|
-
fujin/proxies/nginx.py,sha256=
|
|
27
|
+
fujin/proxies/nginx.py,sha256=S2-tBaytGtehqMyeZZMPSPoXjV1GVv7S63eMtfhkGNM,4100
|
|
28
28
|
fujin/templates/simple.service,sha256=-lyKjmSyfHGucP4O_vRQE1NNaHq0Qjsc0twdwoRLgI0,321
|
|
29
29
|
fujin/templates/web.service,sha256=NZ7ZeaFvV_MZTBn8QqRQeu8PIrWHf3aWYWNzjOQeqCw,685
|
|
30
30
|
fujin/templates/web.socket,sha256=2lJsiOHlMJL0YlN7YBLLnr5zqsytPEt81yP34nk0dmc,173
|
|
31
|
-
fujin_cli-0.
|
|
32
|
-
fujin_cli-0.
|
|
33
|
-
fujin_cli-0.
|
|
34
|
-
fujin_cli-0.
|
|
35
|
-
fujin_cli-0.
|
|
31
|
+
fujin_cli-0.6.0.dist-info/METADATA,sha256=_rYue3Q7z_StHy_Z9DVdaU0RWijde8eWFlm_gwxN4GY,4452
|
|
32
|
+
fujin_cli-0.6.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
33
|
+
fujin_cli-0.6.0.dist-info/entry_points.txt,sha256=Y_TBtKt3j11qhwquMexZR5yqnDEqOBDACtresqQFE-s,46
|
|
34
|
+
fujin_cli-0.6.0.dist-info/licenses/LICENSE.txt,sha256=0QF8XfuH0zkIHhSet6teXfiCze6JSdr8inRkmLLTDyo,1099
|
|
35
|
+
fujin_cli-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|