mirror of
https://github.com/Myzel394/amiopen.now.git
synced 2025-06-18 15:35:27 +02:00
Merge pull request #1 from Myzel394/add-website
This commit is contained in:
commit
d33324d1e8
1
.github/workflows/release.yaml
vendored
1
.github/workflows/release.yaml
vendored
@ -19,4 +19,3 @@ jobs:
|
|||||||
|
|
||||||
- name: Build & upload image
|
- name: Build & upload image
|
||||||
run: ./upload_to_server.sh ${{ secrets.SERVER_IP }} ${{ secrets.SSH_USER }}
|
run: ./upload_to_server.sh ${{ secrets.SERVER_IP }} ${{ secrets.SSH_USER }}
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
FROM oven/bun:alpine
|
FROM oven/bun
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package.json ./
|
COPY . /app
|
||||||
COPY bun.lockb ./
|
|
||||||
COPY src ./src
|
|
||||||
|
|
||||||
RUN bun install
|
RUN bun install --production
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
|
61
flake.lock
generated
Normal file
61
flake.lock
generated
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731676054,
|
||||||
|
"narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"utils": "utils"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
23
flake.nix
Normal file
23
flake.nix
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
description = "A very basic flake";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
|
utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
html-minifier
|
||||||
|
bun
|
||||||
|
vscode-langservers-extracted
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
@ -8,11 +8,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"hono": "^4.6.9",
|
"hono": "^4.6.9",
|
||||||
"ip": "^2.0.1",
|
"ip": "^2.0.1",
|
||||||
|
"nunjucks": "^3.2.4",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@types/ip": "^1.1.3",
|
"@types/ip": "^1.1.3",
|
||||||
|
"@types/nunjucks": "^3.2.6",
|
||||||
"prettier": "^3.3.3"
|
"prettier": "^3.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
src/index.ts
13
src/index.ts
@ -1,10 +1,17 @@
|
|||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { portRoute } from "./routes/port";
|
import { portRoute } from "./routes/port";
|
||||||
import realIP from "./middlewares/real-ip";
|
import { rootRoute } from "./routes/root";
|
||||||
|
import { serveStatic } from "hono/bun";
|
||||||
|
import * as nunjucks from "nunjucks";
|
||||||
|
|
||||||
const app = new Hono();
|
nunjucks.configure("templates", {
|
||||||
|
dev: process.env.NODE_ENV === "development",
|
||||||
|
});
|
||||||
|
|
||||||
app.route("/", portRoute);
|
const app = new Hono()
|
||||||
|
.use("/static/*", serveStatic({ root: "./" }))
|
||||||
|
.route("/", rootRoute)
|
||||||
|
.route("/", portRoute);
|
||||||
|
|
||||||
Bun.serve({
|
Bun.serve({
|
||||||
...app,
|
...app,
|
||||||
|
23
src/middlewares/presentation.ts
Normal file
23
src/middlewares/presentation.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { createMiddleware } from "hono/factory";
|
||||||
|
|
||||||
|
export type PresentationType = "terminal" | "browser";
|
||||||
|
|
||||||
|
const TERMINAL_USER_AGENT = /^(curl|wget|python-urllib|pycurl|java)/i;
|
||||||
|
|
||||||
|
const presentation = createMiddleware<{
|
||||||
|
Variables: {
|
||||||
|
presentation: PresentationType;
|
||||||
|
};
|
||||||
|
}>(async (context, next) => {
|
||||||
|
const userAgent = context.req.header("User-Agent") || "";
|
||||||
|
|
||||||
|
if (TERMINAL_USER_AGENT.test(userAgent)) {
|
||||||
|
context.set("presentation", "terminal");
|
||||||
|
} else {
|
||||||
|
context.set("presentation", "browser");
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
});
|
||||||
|
|
||||||
|
export default presentation;
|
@ -1,9 +1,10 @@
|
|||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { getConnInfo } from "hono/bun";
|
|
||||||
import connectToAddress from "../utils/connect-to-address";
|
import connectToAddress from "../utils/connect-to-address";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import * as IP from "ip";
|
import * as IP from "ip";
|
||||||
import realIP from "../middlewares/real-ip";
|
import realIP from "../middlewares/real-ip";
|
||||||
|
import presentation from "../middlewares/presentation";
|
||||||
|
import render from "../utils/renderer";
|
||||||
|
|
||||||
export const portRoute = new Hono();
|
export const portRoute = new Hono();
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ const schema = z.object({
|
|||||||
.pipe(z.number().min(100).max(60_000)),
|
.pipe(z.number().min(100).max(60_000)),
|
||||||
});
|
});
|
||||||
|
|
||||||
portRoute.get("/:port", realIP, async context => {
|
portRoute.get("/:port", realIP, presentation, async context => {
|
||||||
const rawData = {
|
const rawData = {
|
||||||
ip: context.get("ip"),
|
ip: context.get("ip"),
|
||||||
port: context.req.param("port"),
|
port: context.req.param("port"),
|
||||||
@ -55,12 +56,14 @@ portRoute.get("/:port", realIP, async context => {
|
|||||||
|
|
||||||
const result = await connectToAddress(ip, port, { timeout });
|
const result = await connectToAddress(ip, port, { timeout });
|
||||||
|
|
||||||
return context.json({
|
return render(context, "port", {
|
||||||
|
port: port,
|
||||||
isOpen: result.isOpen,
|
isOpen: result.isOpen,
|
||||||
|
ip: ip,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
portRoute.get("/:ip/:port", async context => {
|
portRoute.get("/:ip/:port", realIP, presentation, async context => {
|
||||||
const rawData = {
|
const rawData = {
|
||||||
ip: context.req.param("ip"),
|
ip: context.req.param("ip"),
|
||||||
port: context.req.param("port"),
|
port: context.req.param("port"),
|
||||||
@ -92,7 +95,9 @@ portRoute.get("/:ip/:port", async context => {
|
|||||||
|
|
||||||
const result = await connectToAddress(ip, port, { timeout });
|
const result = await connectToAddress(ip, port, { timeout });
|
||||||
|
|
||||||
return context.json({
|
return render(context, "port", {
|
||||||
|
port: port,
|
||||||
isOpen: result.isOpen,
|
isOpen: result.isOpen,
|
||||||
|
ip: ip,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
12
src/routes/root.ts
Normal file
12
src/routes/root.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Hono } from "hono";
|
||||||
|
import presentation from "../middlewares/presentation";
|
||||||
|
import realIP from "../middlewares/real-ip";
|
||||||
|
import render from "../utils/renderer";
|
||||||
|
|
||||||
|
export const rootRoute = new Hono();
|
||||||
|
|
||||||
|
rootRoute.get("/", realIP, presentation, context => {
|
||||||
|
return render(context, "index", {
|
||||||
|
ip: context.get("ip"),
|
||||||
|
});
|
||||||
|
});
|
25
src/utils/renderer.ts
Normal file
25
src/utils/renderer.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Context } from "hono";
|
||||||
|
import { PresentationType } from "../middlewares/presentation";
|
||||||
|
import * as nunjucks from "nunjucks";
|
||||||
|
|
||||||
|
export default async function render(
|
||||||
|
context: Context,
|
||||||
|
templateName: "index" | "port",
|
||||||
|
ctx: Record<string, any>,
|
||||||
|
) {
|
||||||
|
const presentation = context.get("presentation") as PresentationType;
|
||||||
|
const extension = {
|
||||||
|
browser: ".html",
|
||||||
|
terminal: ".txt",
|
||||||
|
}[presentation];
|
||||||
|
const key = templateName + extension + ".njk";
|
||||||
|
|
||||||
|
const content = nunjucks.render(key, ctx);
|
||||||
|
|
||||||
|
switch (presentation) {
|
||||||
|
case "browser":
|
||||||
|
return context.html(content);
|
||||||
|
case "terminal":
|
||||||
|
return context.text(content);
|
||||||
|
}
|
||||||
|
}
|
1
static/copy.svg
Normal file
1
static/copy.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z" /></svg>
|
After Width: | Height: | Size: 201 B |
82
templates/base.html.njk
Normal file
82
templates/base.html.njk
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="darkreader-lock">
|
||||||
|
<title>amiopen.now</title>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
background-color: #161318;
|
||||||
|
color: #eee;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
background-color: #212126;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 40em;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: 1em;
|
||||||
|
padding: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socials {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
column-gap: 1em;
|
||||||
|
margin-top: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socials img {
|
||||||
|
color: #fff;
|
||||||
|
filter: invert(0.7);
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
width: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.socials img:hover {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{% block header %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
{% block main %}
|
||||||
|
<h2>Am I Open</h2>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
<div class="socials">
|
||||||
|
<a href="https://github.com/Myzel394/amiopen.now" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="/static/github.svg" alt="GitHub" />
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/Myzel394" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="/static/twitter.svg" alt="GitHub" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% block scripts %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
105
templates/index.html.njk
Normal file
105
templates/index.html.njk
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
{% extends "base.html.njk" %}
|
||||||
|
|
||||||
|
{% block header %}
|
||||||
|
<style type="text/css">
|
||||||
|
code {
|
||||||
|
background-color: #2f2f2f;
|
||||||
|
color: #eee;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
code .command {
|
||||||
|
color: #598eb2;
|
||||||
|
}
|
||||||
|
|
||||||
|
code .input {
|
||||||
|
color: #b27b59;
|
||||||
|
}
|
||||||
|
|
||||||
|
code .second-input {
|
||||||
|
color: #b2596e;
|
||||||
|
}
|
||||||
|
|
||||||
|
code .secondary {
|
||||||
|
color: #b2a559;
|
||||||
|
}
|
||||||
|
|
||||||
|
code .comment {
|
||||||
|
color: #5c6370;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
border-radius: 0.4em;
|
||||||
|
|
||||||
|
aspect-ratio: 1;
|
||||||
|
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy:hover {
|
||||||
|
background: #ffffff40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy img {
|
||||||
|
width: 1rem;
|
||||||
|
color: #fff;
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<h2>Am I Open</h2>
|
||||||
|
<p>
|
||||||
|
Your IP address: <strong>{{ip}}</strong>
|
||||||
|
<button class="copy" id="copy-ip">
|
||||||
|
<img width="1em" src="/static/copy.svg" alt="Copy" />
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<strong> Check if your port is reachable: </strong>
|
||||||
|
<pre><code><span class="command">curl</span> amiopen.now/<span class="input"><port></span>
|
||||||
|
|
||||||
|
<span class="comment">// Example</span>
|
||||||
|
<span class="command">curl</span> amiopen.now/<span class="input">80</span>
|
||||||
|
> open</code></pre>
|
||||||
|
|
||||||
|
<strong> Check if an IP address is reachable: </strong>
|
||||||
|
<pre><code><span class="command">curl</span> amiopen.now/<span class="second-input"><ip address></span>/<span class="input"><port></span>
|
||||||
|
|
||||||
|
<span class="comment">// Example</span>
|
||||||
|
<span class="comment">$</span> <span class="command">curl</span> amiopen.now/<span class="second-input">1.1.1.1</span>/<span class="input">53</span>
|
||||||
|
> open</code></pre>
|
||||||
|
|
||||||
|
<strong> Check if your ISP is blocking a port: </strong>
|
||||||
|
<pre><code><span class="command">telnet</span> amiopen.now <span class="input"><port></span>
|
||||||
|
|
||||||
|
<span class="comment">// Example</span>
|
||||||
|
<span class="command">telnet</span> amiopen.now <span class="input">80</span></code></pre>
|
||||||
|
|
||||||
|
<i>
|
||||||
|
Hint: You can also check if you can access SSH by using:
|
||||||
|
<pre><code><span class="command">ssh</span> <span class="secondary">hello</span>@amiopen.now</code></pre>
|
||||||
|
</i>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script defer>
|
||||||
|
const $copyButton = document.getElementById("copy-ip");
|
||||||
|
const ip = "{{ip}}";
|
||||||
|
|
||||||
|
copyButton.addEventListener("click", () => {
|
||||||
|
navigator.clipboard.writeText(ip);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
1
templates/index.txt.njk
Normal file
1
templates/index.txt.njk
Normal file
@ -0,0 +1 @@
|
|||||||
|
{{ip}}
|
96
templates/port.html.njk
Normal file
96
templates/port.html.njk
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
{% extends "base.html.njk" %}
|
||||||
|
|
||||||
|
{% block header %}
|
||||||
|
<style type="text/css">
|
||||||
|
.status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
column-gap: .6em;
|
||||||
|
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status p {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#icon {
|
||||||
|
width: 0.7em;
|
||||||
|
height: 0.7em;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.success {
|
||||||
|
color: #2ecc71;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.error {
|
||||||
|
color: #e74c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.success #icon {
|
||||||
|
background-color: #2ecc71;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.error #icon {
|
||||||
|
background-color: #e74c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.success #icon::before {
|
||||||
|
content: "";
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #2ecc71;
|
||||||
|
opacity: 0.3;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
transform: scale(2);
|
||||||
|
|
||||||
|
animation: pulse 3s ease-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(2);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<h2>Am I Open</h2>
|
||||||
|
|
||||||
|
<i>{{ ip }}</i>
|
||||||
|
|
||||||
|
{% if isOpen %}
|
||||||
|
<div class="status success">
|
||||||
|
<div id="icon"></div>
|
||||||
|
|
||||||
|
<p>Port <strong>{{port}}</strong> is open</p>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="status error">
|
||||||
|
<div id="icon"></div>
|
||||||
|
|
||||||
|
<p>Port <strong>{{port}}</strong> is closed</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
1
templates/port.txt.njk
Normal file
1
templates/port.txt.njk
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% if isOpen %}open{% else %}closed{% endif %}
|
@ -1,9 +1,8 @@
|
|||||||
ip=$1
|
ip=$1
|
||||||
user=$2
|
user=$2
|
||||||
|
|
||||||
docker buildx build --platform linux/amd64 . --tag amiopen:latest
|
docker buildx build --platform linux/amd64 . --tag amiopen:latest &&
|
||||||
docker save -o amiopen.tar amiopen:latest
|
docker save -o amiopen.tar amiopen:latest &&
|
||||||
|
scp amiopen.tar $user@$ip:~/amiopen/amiopen.tar &&
|
||||||
scp amiopen.tar $user@$ip:~/amiopen/amiopen.tar
|
ssh $user@$ip "cd ~/amiopen && docker container stop amiopen && docker container rm amiopen && docker load -i amiopen.tar && docker compose up -d"
|
||||||
ssh $user@$ip "cd ~/amiopen && docker container stop amiopen && docker container rm amiopen && docker load -i amiopen.tar && docker compose up -d"
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user