nginx #2

Merged
mb merged 10 commits from nginx into master 2024-02-04 00:37:33 +01:00
4 changed files with 55 additions and 20 deletions
Showing only changes of commit 466239d0e6 - Show all commits

View file

@ -2,6 +2,7 @@
import { daemon_listen, Runner } from "./src/lib.ts";
import { ContainerConfig } from "./src/lib/config.ts";
import { NginxController } from "./src/lib/nginx.ts";
import { socket_path, state_path } from "./src/lib/paths.ts";
import { log_from, sleep } from "./src/lib/utils.ts";
@ -78,9 +79,11 @@ async function main() {
class State {
enabled;
nginx;
constructor() {
this.enabled = new Map<string, Runner>();
this.nginx = new NginxController("barnulf.net", "/etc/nginx/sites-enabled");
}
static async load() {
@ -104,7 +107,7 @@ class State {
const config = await ContainerConfig.load(name); // TODO
if (config === null) throw new Error("can't read config");
log("starting container", name);
const runner = new Runner(config);
const runner = new Runner(config, this.nginx);
runner.start();
this.enabled.set(name, runner);
log("container", name, "started");

View file

@ -6,6 +6,7 @@ import { ContainerConfig } from "./lib/config.ts";
import { container_paths } from "./lib/paths.ts";
import { container_command } from "./lib/nspawn.ts";
import { LoopProcess } from "./lib/utils.ts";
import { NginxController } from "./lib/nginx.ts";
const log = log_from("lib");
@ -70,15 +71,22 @@ export async function daemon_send(sock_path: string, command: Cmd) {
export class Runner {
name;
config;
loop: LoopProcess | null;
nginx;
loop;
constructor(config: ContainerConfig) {
constructor(config: ContainerConfig, nginx: NginxController) {
this.name = config.name;
this.config = config;
this.loop = null;
this.nginx = nginx;
this.loop = null as LoopProcess | null;
}
start() {
this.update_proxies();
this.start_process();
}
private start_process() {
const paths = container_paths(name);
const command = container_command(name, paths.root, {
boot: true,
@ -99,4 +107,18 @@ export class Runner {
async stop() {
await this.loop?.kill();
}
async update_proxies() {
const paths = container_paths(name);
await Deno.mkdir(paths.sites, { recursive: true });
const sites = new Set<string>();
for (const redir of this.config.redirections) {
if (redir.kind !== "http") continue;
await this.nginx.add_proxy(redir.domain, redir.port, paths.sites);
sites.add(redir.domain);
}
for await (const domains of this.nginx.read_all_in_dir(paths.sites)) {
if (!sites.has(domains)) this.nginx.remove_proxy(domains, paths.sites);
}
}
}

View file

@ -1,41 +1,50 @@
import { run } from "./utils.ts";
import * as path from "https://deno.land/std@0.214.0/path/mod.ts";
class NginxController {
proxy_target_url;
enabled_conf_dir;
export class NginxController {
private proxy_target_domain;
private enabled_conf_dir;
constructor(proxy_target_url: string, enabled_conf_dir: string) {
this.proxy_target_url = proxy_target_url;
constructor(proxy_target_domain: string, enabled_conf_dir: string) {
this.proxy_target_domain = proxy_target_domain;
this.enabled_conf_dir = enabled_conf_dir;
}
public async add_proxy(url: string, port: number, conf_dir: string) {
public async add_proxy(domain: string, port: number, conf_dir: string) {
const conf_file_content = `
server {
listen 80;
listen [::]:80;
server_name ${url};
server_name ${domain};
location / {
proxy_pass http://${this.proxy_target_url}:${port};
proxy_pass http://${this.proxy_target_domain}:${port};
}
}
`;
const conf_file_path = path.join(conf_dir, url + ".conf");
const enabled_conf_file_path = path.join(this.enabled_conf_dir, url + ".conf");
const conf_file_path = path.join(conf_dir, domain + ".conf");
const enabled_conf_file_path = path.join(this.enabled_conf_dir, domain + ".conf");
await Deno.writeTextFile(conf_file_path, conf_file_content);
await run("ln", "-s", await Deno.realPath(conf_file_path), enabled_conf_file_path);
await this.reload();
return conf_file_path;
}
public async remove_proxy(url: string, conf_dir: string) {
const conf_file_path = path.join(conf_dir, url + ".conf");
const enabled_conf_file_path = path.join(this.enabled_conf_dir, url + ".conf");
await Deno.remove(enabled_conf_file_path);
await Deno.remove(conf_file_path);
public async remove_proxy(domain: string, conf_dir: string) {
const conf_file_path = path.join(conf_dir, domain + ".conf");
const enabled_conf_file_path = path.join(this.enabled_conf_dir, domain + ".conf");
await Deno.remove(enabled_conf_file_path, { recursive: true });
await Deno.remove(conf_file_path, { recursive: true });
await this.reload();
}
public async *read_all_in_dir(conf_dir: string) {
for await (const { name } of Deno.readDir(conf_dir)) {
const [domain, rest] = name.split(".conf");
if (rest !== "") continue;
yield domain;
}
}
private async reload() {
await run("systemctl", "restart", "nginx");
}

View file

@ -18,7 +18,8 @@ export function container_paths(name: string) {
const base = containers_path() + "/" + name;
const configuration = base + "/config.json";
const root = base + "/root";
return { base, configuration, root };
const sites = base + "/sites";
return { base, configuration, root, sites };
}
export function state_path() {