mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
Moving to modules. Structural changes.
This commit is contained in:
parent
3903bc1766
commit
060d4c6d1e
258 changed files with 621 additions and 407 deletions
|
|
@ -1,57 +0,0 @@
|
|||
|
||||
{ config, lib, pkgs, tf, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ports = [ 5160 5060 ];
|
||||
kw.fw.public.udp.ports = [ 5160 5060 ];
|
||||
|
||||
kw.fw.public.tcp.ranges = [{
|
||||
from = 10000;
|
||||
to = 20000;
|
||||
}];
|
||||
|
||||
kw.fw.public.udp.ranges = [{
|
||||
from = 10000;
|
||||
to = 20000;
|
||||
}];
|
||||
|
||||
services.fail2ban.jails = {
|
||||
asterisk = ''
|
||||
enabled = true
|
||||
filter = asterisk
|
||||
action = nftables-allports
|
||||
logpath = /var/log/asterisk/messages
|
||||
maxretry = 4
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ asterisk ];
|
||||
|
||||
users.groups.asterisk = {
|
||||
name = "asterisk";
|
||||
};
|
||||
|
||||
users.users.asterisk = {
|
||||
name = "asterisk";
|
||||
group = "asterisk";
|
||||
home = "/var/lib/asterisk";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
systemd.services.asterisk = {
|
||||
description = "Asterisk PBX Server";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
restartIfChanged = false;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.asterisk}/bin/asterisk -U asterisk -C /etc/asterisk/asterisk.conf -F";
|
||||
ExecReload = "${pkgs.asterisk}/bin/asterisk -x 'core reload'";
|
||||
Type = "forking";
|
||||
PIDFile = "/run/asterisk/asterisk.pid";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.postgresql = {
|
||||
ensureDatabases = [ "bitwarden_rs" ];
|
||||
ensureUsers = [{
|
||||
name = "bitwarden_rs";
|
||||
ensurePermissions = { "DATABASE bitwarden_rs" = "ALL PRIVILEGES"; };
|
||||
}];
|
||||
};
|
||||
|
||||
services.bitwarden_rs = {
|
||||
enable = true;
|
||||
dbBackend = "postgresql";
|
||||
config = {
|
||||
rocketPort = 4000;
|
||||
websocketEnabled = true;
|
||||
signupsAllowed = false;
|
||||
domain = "https://vault.kittywit.ch";
|
||||
databaseUrl = "postgresql://bitwarden_rs@/bitwarden_rs";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."vault.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/".proxyPass = "http://127.0.0.1:4000";
|
||||
"/notifications/hub".proxyPass = "http://127.0.0.1:3012";
|
||||
"/notifications/hub/negotiate".proxyPass = "http://127.0.0.1:80";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_vault = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "vault";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
mailAccounts = config.mailserver.loginAccounts;
|
||||
htpasswd = pkgs.writeText "radicale.users" (concatStrings
|
||||
(flip mapAttrsToList mailAccounts
|
||||
(mail: user: mail + ":" + user.hashedPassword + "\n")));
|
||||
|
||||
in
|
||||
{
|
||||
services.radicale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
auth = {
|
||||
type = "htpasswd";
|
||||
htpasswd_filename = toString htpasswd;
|
||||
htpasswd_encryption = "bcrypt";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"cal.kittywit.ch" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:5232/";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Script-Name /;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_header Authorization;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_cal = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "cal";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
packageFirewall = pkgs.nftables;
|
||||
banaction = "nftables-multiport";
|
||||
banaction-allports = "nftables-allports";
|
||||
jails = {
|
||||
default = ''
|
||||
bantime = 7d
|
||||
blocktype = DROP
|
||||
action = nftables-allports
|
||||
logpath = /var/log/auth.log
|
||||
'';
|
||||
ssh = ''
|
||||
enabled = true
|
||||
filter = sshd
|
||||
maxretry = 4
|
||||
action = nftables-multiport[name=SSH, port=ssh, protocol=tcp]
|
||||
'';
|
||||
sshd-ddos = ''
|
||||
enabled = true
|
||||
filter = sshd-ddos
|
||||
maxretry = 4
|
||||
action = nftables-multiport[name=ssh, port=ssh, protocol=tcp]
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."fail2ban/filter.d/sshd-ddos.conf" = {
|
||||
enable = true;
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = sshd(?:\[\d+\])?: Did not receive identification string from <HOST>$
|
||||
ignoreregex =
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.fail2ban.serviceConfig.LimitSTACK = 128 * 1024;
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "gitea" ];
|
||||
ensureUsers = [{
|
||||
name = "gitea";
|
||||
ensurePermissions."DATABASE gitea" = "ALL PRIVILEGES";
|
||||
}];
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
disableRegistration = true;
|
||||
domain = "git.kittywit.ch";
|
||||
rootUrl = "https://git.kittywit.ch";
|
||||
httpAddress = "127.0.0.1";
|
||||
appName = "kittywitch git";
|
||||
ssh = { clonePort = 62954; };
|
||||
database = {
|
||||
type = "postgres";
|
||||
name = "gitea";
|
||||
user = "gitea";
|
||||
};
|
||||
settings = {
|
||||
security = { DISABLE_GIT_HOOKS = false; };
|
||||
api = { ENABLE_SWAGGER = true; };
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
MAILER_TYPE = "sendmail";
|
||||
FROM = "gitea@kittywit.ch";
|
||||
SENDMAIL_PATH = "${pkgs.system-sendmail}/bin/sendmail";
|
||||
};
|
||||
ui = {
|
||||
THEMES = "gitea,arc-green";
|
||||
DEFAULT_THEME = "gitea";
|
||||
THEME_COLOR_META_TAG = "#222222";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.gitea.preStart = ''
|
||||
${pkgs.coreutils}/bin/ln -sfT ${./public} /var/lib/gitea/custom/public
|
||||
${pkgs.coreutils}/bin/ln -sfT ${./templates} /var/lib/gitea/custom/templates
|
||||
'';
|
||||
|
||||
services.nginx.virtualHosts."git.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = { "/".proxyPass = "http://127.0.0.1:3000"; };
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_git = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "git";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 171.19"><defs><style>.cls-1,.cls-3{stroke:#000;stroke-miterlimit:10;}.cls-2{fill:#ccc;}.cls-3,.cls-4{fill:#f2f2f2;}</style></defs><path class="cls-1" d="M403.84,463.72s13.51-20.52,9.51-44.75c0,0-22.62-2.63-38,12.5C361.41,402.18,345.28,369,369.47,345c0,0,8,5.45,8.47,12.71,2,31.08-1.18,31.53-1.18,31.53,25.3-3.77,32.51-45.12,9.89-59.77-55.53-26.12-63.59-4.21-71.3,42.35-3.2,27.07-3.83,41.66-8.19,62.74-13.46-15.72-38.59-14.19-38-14-3.4,25,7.88,45.73,9.45,46.09-15,4.55-37.67,6.71-73,11.28,75.87,17.66,199,11.15,274.58-4.94C468.23,470.85,414.31,471.71,403.84,463.72Z" transform="translate(-202.9 -317.79)"/><polygon class="cls-2" points="98.68 121.45 90.04 110.5 90.44 120.65 75.53 115.4 83.03 130.62 71.94 130.38 81.58 144.37 98.68 121.45"/><path class="cls-3" d="M305.65,436.85" transform="translate(-202.9 -317.79)"/><path class="cls-4" d="M301.65,439.44l-.07-.2a85.43,85.43,0,0,0-6.65-5.65l0,6.41s-6,1.47-10.83-1.78c0,0,7.18,11.33,1.07,11.54a40.37,40.37,0,0,0-5.48.5l4.78,11.9C299.42,459.81,301.81,444.69,301.65,439.44Z" transform="translate(-202.9 -317.79)"/><polygon class="cls-2" points="179.03 119.28 187.68 108.33 187.28 118.47 202.19 113.22 194.69 128.44 205.78 128.21 196.13 142.19 179.03 119.28"/><path class="cls-4" d="M381.87,437.27l.07-.2a83.13,83.13,0,0,1,6.65-5.66l0,6.41s6,1.47,10.83-1.78c0,0-7.18,11.33-1.07,11.55a38.39,38.39,0,0,1,5.48.5L399,460C384.1,457.63,381.71,442.51,381.87,437.27Z" transform="translate(-202.9 -317.79)"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,29 +0,0 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
|
||||
<a class="item {{if .PageIsAdminDashboard}}acty{{end}}" href="{{AppSubUrl}}/admin">
|
||||
{{.i18n.Tr "admin.dashboard"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminUsers}}acty{{end}}" href="{{AppSubUrl}}/admin/users">
|
||||
{{.i18n.Tr "admin.users"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminOrganizations}}acty{{end}}" href="{{AppSubUrl}}/admin/orgs">
|
||||
{{.i18n.Tr "admin.organizations"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminRepositories}}acty{{end}}" href="{{AppSubUrl}}/admin/repos">
|
||||
{{.i18n.Tr "admin.repositories"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminHooks}}acty{{end}}" href="{{AppSubUrl}}/admin/hooks">
|
||||
{{.i18n.Tr "admin.hooks"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminAuthentications}}acty{{end}}" href="{{AppSubUrl}}/admin/auths">
|
||||
{{.i18n.Tr "admin.authentication"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminConfig}}acty{{end}}" href="{{AppSubUrl}}/admin/config">
|
||||
{{.i18n.Tr "admin.config"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminNotices}}acty{{end}}" href="{{AppSubUrl}}/admin/notices">
|
||||
{{.i18n.Tr "admin.notices"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminMonitor}}acty{{end}}" href="{{AppSubUrl}}/admin/monitor">
|
||||
{{.i18n.Tr "admin.monitor"}}
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head data-suburl="{{AppSubUrl}}">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
|
||||
<link rel="manifest" href="{{AppSubUrl}}/manifest.json">
|
||||
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) {
|
||||
// Registration was successful
|
||||
console.log('ServiceWorker registration successful with scope: ', registration.scope);
|
||||
}, function(err) {
|
||||
// registration failed :(
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
|
||||
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" />
|
||||
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" />
|
||||
<meta name="keywords" content="{{MetaKeywords}}">
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<meta name="_csrf" content="{{.CsrfToken}}" />
|
||||
<meta name="_suburl" content="{{AppSubUrl}}" />
|
||||
{{if .IsSigned}}
|
||||
<meta name="_uid" content="{{.SignedUser.ID}}" />
|
||||
{{end}}
|
||||
{{if .ContextUser}}
|
||||
<meta name="_context_uid" content="{{.ContextUser.ID}}" />
|
||||
{{end}}
|
||||
{{if .SearchLimit}}
|
||||
<meta name="_search_limit" content="{{.SearchLimit}}" />
|
||||
{{end}}
|
||||
{{if .GoGetImport}}
|
||||
<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">
|
||||
<meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}">
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
{{SafeJS `/*
|
||||
@licstart The following is the entire license notice for the
|
||||
JavaScript code in this page.
|
||||
|
||||
Copyright (c) 2016 The Gitea Authors
|
||||
Copyright (c) 2015 The Gogs Authors
|
||||
|
||||
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.
|
||||
---
|
||||
Licensing information for additional javascript libraries can be found at:
|
||||
{{AppSubUrl}}/vendor/librejs.html
|
||||
|
||||
@licend The above is the entire license notice
|
||||
for the JavaScript code in this page.
|
||||
*/`}}
|
||||
</script>
|
||||
|
||||
<link rel="shortcut icon" href="{{AppSubUrl}}/img/favicon.png" />
|
||||
<link rel="mask-icon" href="{{AppSubUrl}}/img/gitea-safari.svg" color="#609926">
|
||||
<link rel="preload" href="{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css" as="style" onload="this.rel='stylesheet'">
|
||||
<noscript><link rel="stylesheet" href="{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css"></noscript>
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/assets/octicons/octicons.min.css">
|
||||
|
||||
{{if .RequireSimpleMDE}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.css">
|
||||
{{end}}
|
||||
|
||||
{{if .RequireGitGraph}}
|
||||
<!-- graph -->
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.css">
|
||||
{{end}}
|
||||
|
||||
{{if .RequireTribute}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/tribute/tribute.css">
|
||||
{{end}}
|
||||
|
||||
<!-- Stylesheet -->
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.css">
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/index.css?v={{MD5 AppVer}}">
|
||||
<noscript>
|
||||
<style>
|
||||
.dropdown:hover > .menu { display: block; }
|
||||
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; }
|
||||
</style>
|
||||
</noscript>
|
||||
|
||||
{{if .RequireHighlightJS}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/highlight/github.css">
|
||||
{{end}}
|
||||
{{if .RequireMinicolors}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
|
||||
{{end}}
|
||||
{{if .RequireDatetimepicker}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css">
|
||||
{{end}}
|
||||
{{if .RequireDropzone}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css">
|
||||
{{end}}
|
||||
{{if .EnableHeatmap}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/vue-calendar-heatmap/vue-calendar-heatmap.css">
|
||||
{{end}}
|
||||
<style class="list-search-style"></style>
|
||||
|
||||
<script src="{{AppSubUrl}}/vendor/plugins/cssrelpreload/loadCSS.min.js"></script>
|
||||
<script src="{{AppSubUrl}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js"></script>
|
||||
{{if .PageIsUserProfile}}
|
||||
<meta property="og:title" content="{{.Owner.Name}}" />
|
||||
<meta property="og:type" content="profile" />
|
||||
<meta property="og:image" content="{{.Owner.AvatarLink}}" />
|
||||
<meta property="og:url" content="{{.Owner.HTMLURL}}" />
|
||||
<meta property="og:site_name" content="{{AppName}}" />
|
||||
{{else if .Repository}}
|
||||
<meta property="og:title" content="{{.Repository.Name}}" />
|
||||
<meta property="og:type" content="object" />
|
||||
<meta property="og:image" content="{{.Repository.Owner.AvatarLink}}" />
|
||||
<meta property="og:url" content="{{.Repository.HTMLURL}}" />
|
||||
{{if .Repository.Description}}
|
||||
<meta property="og:description" content="{{.Repository.Description}}" />
|
||||
{{end}}
|
||||
<meta property="og:site_name" content="{{AppName}}" />
|
||||
{{else}}
|
||||
<meta property="og:title" content="{{AppName}}">
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image" content="{{AppSubUrl}}/img/gitea-lg.png" />
|
||||
<meta property="og:url" content="{{AppUrl}}" />
|
||||
<meta property="og:description" content="{{MetaDescription}}">
|
||||
{{end}}
|
||||
{{if .IsSigned }}
|
||||
{{ if ne .SignedUser.Theme "gitea" }}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{.SignedUser.Theme}}.css">
|
||||
{{end}}
|
||||
{{else if ne DefaultTheme "gitea"}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css">
|
||||
{{end}}
|
||||
{{template "custom/header" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "custom/body_outer_pre" .}}
|
||||
|
||||
<div class="full height">
|
||||
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript>
|
||||
|
||||
{{template "custom/body_inner_pre" .}}
|
||||
|
||||
{{if not .PageIsInstall}}
|
||||
<div class="ui top secondary stackable main menu following bar light">
|
||||
{{template "base/head_navbar" .}}
|
||||
</div><!-- end bar -->
|
||||
{{end}}
|
||||
{{/*
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
*/}}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless stackable menu navbar">
|
||||
<a class="item {{if .PageIsExploreRepositories}}acty{{end}}" href="{{AppSubUrl}}/explore/repos">
|
||||
{{svg "octicon-repo" 16}} {{.i18n.Tr "explore.repos"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsExploreUsers}}acty{{end}}" href="{{AppSubUrl}}/explore/users">
|
||||
{{svg "octicon-person" 16}} {{.i18n.Tr "explore.users"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsExploreOrganizations}}acty{{end}}" href="{{AppSubUrl}}/explore/organizations">
|
||||
{{svg "octicon-organization" 16}} {{.i18n.Tr "explore.organizations"}}
|
||||
</a>
|
||||
{{if .IsRepoIndexerEnabled}}
|
||||
<a class="item {{if .PageIsExploreCode}}acty{{end}}" href="{{AppSubUrl}}/explore/code">
|
||||
{{svg "octicon-code" 16}} {{.i18n.Tr "explore.code"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{{template "base/head" .}}
|
||||
<div class="home">
|
||||
<div class="ui stackable middle very relaxed page grid">
|
||||
<div class="sixteen wide center aligned centered column">
|
||||
<div>
|
||||
<img class="logo" src="{{StaticUrlPrefix}}/img/gitea-lg.png" />
|
||||
</div>
|
||||
<div class="hero">
|
||||
<br />
|
||||
<h1 class="ui icon header title">
|
||||
{{AppName}}
|
||||
</h1>
|
||||
<a href="https://kittywit.ch"><h2>back to home</h2></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
<div class="header-wrapper">
|
||||
{{with .Repository}}
|
||||
<div class="ui container">
|
||||
<div class="repo-header">
|
||||
<div class="ui huge breadcrumb repo-title">
|
||||
{{if .RelAvatarLink}}
|
||||
<img class="ui avatar image" src="{{.RelAvatarLink}}">
|
||||
{{else if .IsTemplate}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-repo-template-private" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo-template" 32}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-lock" 32}}
|
||||
{{else if .IsMirror}}
|
||||
{{svg "octicon-repo-clone" 32}}
|
||||
{{else if .IsFork}}
|
||||
{{svg "octicon-repo-fork" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo" 32}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
|
||||
<div class="divider"> / </div>
|
||||
<a href="{{$.RepoLink}}">{{.Name}}</a>
|
||||
{{if .RelAvatarLink}}
|
||||
{{if .IsTemplate}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-repo-template-private" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo-template" 32}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-lock" 32}}
|
||||
{{else if .IsMirror}}
|
||||
{{svg "octicon-repo-clone" 32}}
|
||||
{{else if .IsFork}}
|
||||
{{svg "octicon-repo-fork" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo" 32}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
|
||||
{{if .IsMirror}}<div class="fork-flag">{{$.i18n.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}">{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}</a></div>{{end}}
|
||||
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}}
|
||||
{{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{SubStr .TemplateRepo.RelLink 1 -1}}</a></div>{{end}}
|
||||
</div>
|
||||
{{if not .IsBeingCreated}}
|
||||
<div class="repo-buttons">
|
||||
<div class="ui labeled button" tabindex="0">
|
||||
<a class="ui compact basic button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
|
||||
<i class="icon fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}}
|
||||
</a>
|
||||
<a class="ui basic label" href="{{.Link}}/watchers">
|
||||
{{.NumWatches}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="ui labeled button" tabindex="0">
|
||||
<a class="ui compact basic button" href="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}un{{end}}star?redirect_to={{$.Link}}">
|
||||
<i class="icon star{{if not $.IsStaringRepo}} outline{{end}}"></i>{{if $.IsStaringRepo}}{{$.i18n.Tr "repo.unstar"}}{{else}}{{$.i18n.Tr "repo.star"}}{{end}}
|
||||
</a>
|
||||
<a class="ui basic label" href="{{.Link}}/stars">
|
||||
{{.NumStars}}
|
||||
</a>
|
||||
</div>
|
||||
{{if and (not .IsEmpty) ($.Permission.CanRead $.UnitTypeCode)}}
|
||||
<div class="ui labeled button {{if and ($.IsSigned) (not $.CanSignedUserFork)}}disabled-repo-button{{end}}" tabindex="0">
|
||||
<a class="ui compact basic button {{if or (not $.IsSigned) (not $.CanSignedUserFork)}}poping up{{end}}" {{if $.CanSignedUserFork}}href="{{AppSubUrl}}/repo/fork/{{.ID}}"{{else if $.IsSigned}} data-content="{{$.i18n.Tr "repo.fork_from_self"}}" {{ else }} data-content="{{$.i18n.Tr "repo.fork_guest_user" }}" rel="nofollow" href="{{AppSubUrl}}/user/login?redirect_to={{AppSubUrl}}/repo/fork/{{.ID}}" {{end}} data-position="top center" data-variation="tiny">
|
||||
{{svg "octicon-repo-forked" 16}}{{$.i18n.Tr "repo.fork"}}
|
||||
</a>
|
||||
<a class="ui basic label" href="{{.Link}}/forks">
|
||||
{{.NumForks}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div><!-- end grid -->
|
||||
</div><!-- end container -->
|
||||
{{end}}
|
||||
<div class="ui tabs container">
|
||||
{{if not .Repository.IsBeingCreated}}
|
||||
<div class="ui tabular stackable menu navbar">
|
||||
{{if .Permission.CanRead $.UnitTypeCode}}
|
||||
<a class="item {{if .PageIsViewCode}}acty{{end}}" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">
|
||||
{{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if .Permission.CanRead $.UnitTypeIssues}}
|
||||
<a class="item {{if .PageIsIssueList}}acty{{end}}" href="{{.RepoLink}}/issues">
|
||||
{{svg "octicon-issue-opened" 16}} {{.i18n.Tr "repo.issues"}} <span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if .Permission.CanRead $.UnitTypeExternalTracker}}
|
||||
<a class="item {{if .PageIsIssueList}}acty{{end}}" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer">
|
||||
{{svg "octicon-link-external" 16}} {{.i18n.Tr "repo.issues"}} </span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}}
|
||||
<a class="item {{if .PageIsPullList}}acty{{end}}" href="{{.RepoLink}}/pulls">
|
||||
{{svg "octicon-git-pull-request" 16}} {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and (.Permission.CanRead $.UnitTypeReleases) (not .IsEmptyRepo) }}
|
||||
<a class="item {{if .PageIsReleaseList}}acty{{end}}" href="{{.RepoLink}}/releases">
|
||||
{{svg "octicon-tag" 16}} {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .NumReleases}}gray{{else}}blue{{end}} small label">{{.NumReleases}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}}
|
||||
<a class="item {{if .PageIsWiki}}acty{{end}}" href="{{.RepoLink}}/wiki" {{if (.Permission.CanRead $.UnitTypeExternalWiki)}} target="_blank" rel="noopener noreferrer" {{end}}>
|
||||
{{svg "octicon-book" 16}} {{.i18n.Tr "repo.wiki"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}}
|
||||
<a class="item {{if .PageIsActivity}}acty{{end}}" href="{{.RepoLink}}/activity">
|
||||
{{svg "octicon-pulse" 16}} {{.i18n.Tr "repo.activity"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{template "custom/extra_tabs" .}}
|
||||
|
||||
{{if .Permission.IsAdmin}}
|
||||
<div class="right menu">
|
||||
<a class="item {{if .PageIsSettings}}acty{{end}}" href="{{.RepoLink}}/settings">
|
||||
{{svg "octicon-tools" 16}} {{.i18n.Tr "repo.settings"}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui tabs divider"></div>
|
||||
</div>
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
{{template "base/head" .}}
|
||||
<div class="repository file list">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container">
|
||||
{{template "base/alert" .}}
|
||||
<div class="ui repo-description">
|
||||
<div id="repo-desc">
|
||||
{{if .Repository.DescriptionHTML}}<span class="description has-emoji">{{.Repository.DescriptionHTML}}</span>{{else if .IsRepositoryAdmin}}<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span>{{end}}
|
||||
<a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a>
|
||||
</div>
|
||||
{{if .RepoSearchEnabled}}
|
||||
<div class="ui repo-search">
|
||||
<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
|
||||
<div class="field">
|
||||
<div class="ui action input">
|
||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "repo.search.search_repo"}}">
|
||||
<button class="ui icon button" type="submit">
|
||||
<i class="search icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui" id="repo-topics">
|
||||
{{range .Topics}}<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
|
||||
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<a id="manage_topic">{{.i18n.Tr "repo.topic.manage_topics"}}</a>{{end}}
|
||||
</div>
|
||||
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}
|
||||
<div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none">
|
||||
<div class="fourteen wide column">
|
||||
<div class="field">
|
||||
<div class="ui fluid multiple search selection dropdown">
|
||||
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if lt (Add $i 1) (len $.Topics)}},{{end}}{{end}}">
|
||||
{{range .Topics}}
|
||||
<div class="ui small label topic transition visible" data-value="{{.Name}}" style="display: inline-block !important; cursor: default;">{{.Name}}<i class="delete icon"></i></div>
|
||||
{{end}}
|
||||
<div class="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="two wide column">
|
||||
<a class="ui button primary" href="javascript:;" id="save_topic"
|
||||
data-link="{{.RepoLink}}/topics">{{.i18n.Tr "repo.topic.done"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="hide" id="validate_prompt">
|
||||
<span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span>
|
||||
<span id="format_prompt">{{.i18n.Tr "repo.topic.format_prompt"}}</span>
|
||||
</div>
|
||||
{{if .Repository.IsArchived}}
|
||||
<div class="ui warning message">
|
||||
{{.i18n.Tr "repo.archive.title"}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "repo/sub_menu" .}}
|
||||
<div class="ui stackable secondary menu mobile--margin-between-items mobile--no-negative-margins">
|
||||
{{template "repo/branch_dropdown" .}}
|
||||
{{ $n := len .TreeNames}}
|
||||
{{ $l := Subtract $n 1}}
|
||||
<!-- If home page, show new PR. If not, show breadcrumb -->
|
||||
{{if eq $n 0}}
|
||||
{{if and .PullRequestCtx.Allowed .IsViewBranch (not .Repository.IsArchived)}}
|
||||
<div class="fitted item">
|
||||
<a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}">
|
||||
<button id="new-pull-request" class="ui compact basic button">{{.i18n.Tr "repo.pulls.compare_changes"}}</button>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="fitted item"><span class="ui breadcrumb repo-path"><a class="section" href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{ $p := index $.Paths $i}}<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
|
||||
{{end}}
|
||||
<div class="right fitted item" id="file-buttons">
|
||||
<div class="ui tiny blue buttons">
|
||||
{{if .Repository.CanEnableEditor}}
|
||||
{{if .CanAddFile}}
|
||||
<a href="{{.RepoLink}}/_new/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
|
||||
{{.i18n.Tr "repo.editor.new_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .CanUploadFile}}
|
||||
<a href="{{.RepoLink}}/_upload/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
|
||||
{{.i18n.Tr "repo.editor.upload_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame) }}
|
||||
<a href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}" class="ui button">
|
||||
{{.i18n.Tr "repo.file_history"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="fitted item">
|
||||
{{if eq $n 0}}
|
||||
{{if .Repository.IsTemplate}}
|
||||
<div class="ui tiny blue buttons">
|
||||
<a href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}" class="ui button">
|
||||
{{.i18n.Tr "repo.use_template"}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="fitted item">
|
||||
|
||||
<!-- Only show clone panel in repository home page -->
|
||||
{{if eq $n 0}}
|
||||
<div class="ui action tiny input" id="clone-panel">
|
||||
{{if not $.DisableHTTP}}
|
||||
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
|
||||
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
|
||||
<button class="ui basic clone button" id="repo-clone-ssh" data-link="{{.CloneLink.SSH}}">
|
||||
SSH
|
||||
</button>
|
||||
{{end}}
|
||||
{{if not $.DisableHTTP}}
|
||||
<input id="repo-clone-url" value="{{$.CloneLink.HTTPS}}" readonly>
|
||||
{{else if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
|
||||
<input id="repo-clone-url" value="{{$.CloneLink.SSH}}" readonly>
|
||||
{{end}}
|
||||
{{if or (not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH))}}
|
||||
<button class="ui basic icon button poping up clipboard" id="clipboard-btn" data-original="{{.i18n.Tr "repo.copy_link"}}" data-success="{{.i18n.Tr "repo.copy_link_success"}}" data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-target="#repo-clone-url">
|
||||
{{svg "octicon-clippy" 16}}
|
||||
</button>
|
||||
{{end}}
|
||||
<div class="ui basic jump dropdown icon button poping up" data-content="{{.i18n.Tr "repo.download_archive"}}" data-variation="tiny inverted" data-position="top right">
|
||||
<i class="download icon"></i>
|
||||
<div class="menu">
|
||||
<a class="item" href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.zip">{{svg "octicon-file-zip" 16}} ZIP</a>
|
||||
<a class="item" href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.tar.gz">{{svg "octicon-file-zip" 16}} TAR.GZ</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsViewFile}}
|
||||
{{template "repo/view_file" .}}
|
||||
{{else if .IsBlame}}
|
||||
{{template "repo/blame" .}}
|
||||
{{else}}
|
||||
{{template "repo/view_list" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
|
||||
<a class="item {{if .PageIsSettingsOptions}}acty{{end}}" href="{{.RepoLink}}/settings">
|
||||
{{.i18n.Tr "repo.settings.options"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsCollaboration}}acty{{end}}" href="{{.RepoLink}}/settings/collaboration">
|
||||
{{.i18n.Tr "repo.settings.collaboration"}}
|
||||
</a>
|
||||
{{if not .Repository.IsEmpty}}
|
||||
<a class="item {{if .PageIsSettingsBranches}}acty{{end}}" href="{{.RepoLink}}/settings/branches">
|
||||
{{.i18n.Tr "repo.settings.branches"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item {{if .PageIsSettingsHooks}}acty{{end}}" href="{{.RepoLink}}/settings/hooks">
|
||||
{{.i18n.Tr "repo.settings.hooks"}}
|
||||
</a>
|
||||
{{if .SignedUser.CanEditGitHook}}
|
||||
<a class="item {{if .PageIsSettingsGitHooks}}acty{{end}}" href="{{.RepoLink}}/settings/hooks/git">
|
||||
{{.i18n.Tr "repo.settings.githooks"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item {{if .PageIsSettingsKeys}}acty{{end}}" href="{{.RepoLink}}/settings/keys">
|
||||
{{.i18n.Tr "repo.settings.deploy_keys"}}
|
||||
</a>
|
||||
{{if .LFSStartServer}}
|
||||
<a class="item {{if .PageIsSettingsLFS}}acty{{end}}" href="{{.RepoLink}}/settings/lfs">
|
||||
{{.i18n.Tr "repo.settings.lfs"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
{{template "base/head" .}}
|
||||
<div class="dashboard feeds">
|
||||
{{template "user/dashboard/navbar" .}}
|
||||
<div class="ui container">
|
||||
{{template "base/alert" .}}
|
||||
<div class="ui mobile reversed stackable grid">
|
||||
<div class="ui container ten wide column">
|
||||
{{if .EnableHeatmap}}
|
||||
<div id="user-heatmap" style="padding-right: 40px">
|
||||
<activity-heatmap :locale="locale" :suburl="suburl" :user="heatmapUser">
|
||||
<div slot="loading">
|
||||
<div class="ui active centered inline indeterminate text loader" id="loading-heatmap">{{.i18n.Tr "user.heatmap.loading"}}</div>
|
||||
</div>
|
||||
</activity-heatmap>
|
||||
<div class="ui divider"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "user/dashboard/feeds" .}}
|
||||
</div>
|
||||
<div id="app" class="six wide column">
|
||||
<repo-search
|
||||
:search-limit="searchLimit"
|
||||
:suburl="suburl"
|
||||
:uid="uid"
|
||||
:more-repos-link="'{{.ContextUser.HomeLink}}'"
|
||||
{{if not .ContextUser.IsOrganization}}
|
||||
:organizations="[
|
||||
{{range .ContextUser.Orgs}}
|
||||
{name: '{{.Name}}', num_repos: '{{.NumRepos}}'},
|
||||
{{end}}
|
||||
]"
|
||||
:is-organization="false"
|
||||
:organizations-total-count="{{.ContextUser.GetOrganizationCount}}"
|
||||
:can-create-organization="{{.SignedUser.CanCreateOrganization}}"
|
||||
{{end}}
|
||||
inline-template
|
||||
v-cloak
|
||||
>
|
||||
<div>
|
||||
<div v-if="!isOrganization" class="ui two item tabable menu">
|
||||
<a :class="{item: true, acty: tab === 'repos'}" @click="changeTab('repos')">{{.i18n.Tr "repository"}}</a>
|
||||
<a :class="{item: true, acty: tab === 'organizations'}" @click="changeTab('organizations')">{{.i18n.Tr "organization"}}</a>
|
||||
</div>
|
||||
<div v-show="tab === 'repos'" class="ui tab active list dashboard-repos">
|
||||
<h4 class="ui top attached header">
|
||||
{{.i18n.Tr "home.my_repos"}} <span class="ui grey label">${reposTotalCount}</span>
|
||||
{{if or (not .ContextUser.IsOrganization) .IsOrganizationOwner}}
|
||||
<div class="ui right">
|
||||
<a class="poping up" :href="suburl + '/repo/create{{if .ContextUser.IsOrganization}}?org={{.ContextUser.ID}}{{end}}'" data-content="{{.i18n.Tr "new_repo"}}" data-variation="tiny inverted" data-position="left center">
|
||||
<i class="plus icon"></i>
|
||||
<span class="sr-only">{{.i18n.Tr "new_repo"}}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</h4>
|
||||
<div class="ui attached secondary segment repos-search">
|
||||
<div class="ui fluid icon input" :class="{loading: isLoading}">
|
||||
<input @input="searchRepos(reposFilter)" v-model="searchQuery" ref="search" placeholder="{{.i18n.Tr "home.search_repos"}}">
|
||||
<i class="search icon"></i>
|
||||
</div>
|
||||
<div class="ui secondary tiny pointing borderless menu center aligned grid repos-filter">
|
||||
<a class="item" :class="{acty: reposFilter === 'all'}" @click="changeReposFilter('all')">
|
||||
{{.i18n.Tr "all"}}
|
||||
<div v-show="reposFilter === 'all'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'sources'}" @click="changeReposFilter('sources')">
|
||||
{{.i18n.Tr "sources"}}
|
||||
<div v-show="reposFilter === 'sources'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'forks'}" @click="changeReposFilter('forks')">
|
||||
{{.i18n.Tr "forks"}}
|
||||
<div v-show="reposFilter === 'forks'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'mirrors'}" @click="changeReposFilter('mirrors')">
|
||||
{{.i18n.Tr "mirrors"}}
|
||||
<div v-show="reposFilter === 'mirrors'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'collaborative'}" @click="changeReposFilter('collaborative')">
|
||||
{{.i18n.Tr "collaborative"}}
|
||||
<div v-show="reposFilter === 'collaborative'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached table segment">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo, reposFilter)">
|
||||
<a :href="suburl + '/' + repo.full_name">
|
||||
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="staticPrefix + '/img/svg/icons.svg#' + repoClass(repo)" /></svg>
|
||||
<strong class="text truncate item-name">${repo.full_name}</strong>
|
||||
<i v-if="repo.archived" class="archive icon archived-icon"></i>
|
||||
<span class="ui right text light grey">
|
||||
${repo.stars_count} <span class="rear">{{svg "octicon-star" 16}}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="showMoreReposLink">
|
||||
<a :href="moreReposLink">{{.i18n.Tr "home.show_more_repos"}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isOrganization" v-show="tab === 'organizations'" class="ui tab active list">
|
||||
<h4 class="ui top attached header">
|
||||
{{.i18n.Tr "home.my_orgs"}} <span class="ui grey label">${organizationsTotalCount}</span>
|
||||
<div v-if="canCreateOrganization" class="ui right">
|
||||
<a class="poping up" :href="suburl + '/org/create'" data-content="{{.i18n.Tr "new_org"}}" data-variation="tiny inverted" data-position="left center">
|
||||
<i class="plus icon"></i>
|
||||
<span class="sr-only">{{.i18n.Tr "new_org"}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached table segment">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li v-for="org in organizations">
|
||||
<a :href="suburl + '/' + org.name">
|
||||
{{svg "octicon-organization" 16}}
|
||||
<strong class="text truncate item-name">${org.name}</strong>
|
||||
<span class="ui right text light grey">
|
||||
${org.num_repos} <span class="rear">{{svg "octicon-repo" 16}}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</repo-search>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
|
||||
<a class="item {{if .PageIsSettingsProfile}}acty{{end}}" href="{{AppSubUrl}}/user/settings">
|
||||
{{.i18n.Tr "settings.profile"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsAccount}}acty{{end}}" href="{{AppSubUrl}}/user/settings/account">
|
||||
{{.i18n.Tr "settings.account"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsSecurity}}acty{{end}}" href="{{AppSubUrl}}/user/settings/security">
|
||||
{{.i18n.Tr "settings.security"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsApplications}}acty{{end}}" href="{{AppSubUrl}}/user/settings/applications">
|
||||
{{.i18n.Tr "settings.applications"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsKeys}}acty{{end}}" href="{{AppSubUrl}}/user/settings/keys">
|
||||
{{.i18n.Tr "settings.ssh_gpg_keys"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsOrganization}}acty{{end}}" href="{{AppSubUrl}}/user/settings/organization">
|
||||
{{.i18n.Tr "settings.organization"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsRepos}}acty{{end}}" href="{{AppSubUrl}}/user/settings/repos">
|
||||
{{.i18n.Tr "settings.repos"}}
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
services.postgresql = {
|
||||
ensureDatabases = [ "grafana" ];
|
||||
ensureUsers = [{
|
||||
name = "grafana";
|
||||
ensurePermissions."DATABASE grafana" = "ALL PRIVILEGES";
|
||||
}];
|
||||
};
|
||||
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
port = 3001;
|
||||
domain = "graph.kittywit.ch";
|
||||
rootUrl = "https://graph.kittywit.ch/";
|
||||
database = {
|
||||
type = "postgres";
|
||||
host = "/run/postgresql/";
|
||||
user = "grafana";
|
||||
name = "grafana";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."graph.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = { "/".proxyPass = "http://127.0.0.1:3001"; };
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_graph = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "graph";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
services.logrotate = {
|
||||
enable = true;
|
||||
paths = {
|
||||
nginx = mkIf config.services.nginx.enable {
|
||||
path = "/var/log/nginx/*.log";
|
||||
user = "nginx";
|
||||
group = "nginx";
|
||||
frequency = "weekly";
|
||||
keep = 2;
|
||||
};
|
||||
asterisk = mkIf config.systemd.services.asterisk.enable {
|
||||
path = "/var/log/asterisk/messages";
|
||||
user = "asterisk";
|
||||
group = "asterisk";
|
||||
frequency = "daily";
|
||||
keep = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = [ 3100 ];
|
||||
services.loki = {
|
||||
enable = true;
|
||||
configuration = {
|
||||
auth_enabled = false;
|
||||
chunk_store_config = { max_look_back_period = "0s"; };
|
||||
ingester = {
|
||||
chunk_idle_period = "1h";
|
||||
chunk_retain_period = "30s";
|
||||
chunk_target_size = 1048576;
|
||||
lifecycler = {
|
||||
address = "0.0.0.0";
|
||||
final_sleep = "0s";
|
||||
ring = {
|
||||
kvstore = { store = "inmemory"; };
|
||||
replication_factor = 1;
|
||||
};
|
||||
};
|
||||
max_chunk_age = "1h";
|
||||
max_transfer_retries = 0;
|
||||
};
|
||||
limits_config = {
|
||||
reject_old_samples = true;
|
||||
reject_old_samples_max_age = "168h";
|
||||
};
|
||||
schema_config = {
|
||||
configs = [{
|
||||
from = "2020-10-24";
|
||||
index = {
|
||||
period = "24h";
|
||||
prefix = "index_";
|
||||
};
|
||||
object_store = "filesystem";
|
||||
schema = "v11";
|
||||
store = "boltdb-shipper";
|
||||
}];
|
||||
};
|
||||
compactor = {
|
||||
working_directory = "/tmp/loki-compactor-boltdb";
|
||||
shared_store = "filesystem";
|
||||
};
|
||||
server = { http_listen_port = 3100; };
|
||||
storage_config = {
|
||||
boltdb_shipper = {
|
||||
active_index_directory = "/var/lib/loki/boltdb-shipper-active";
|
||||
cache_location = "/var/lib/loki/boltdb-shipper-cache";
|
||||
cache_ttl = "24h";
|
||||
shared_store = "filesystem";
|
||||
};
|
||||
filesystem = { directory = "/var/lib/loki/chunks"; };
|
||||
};
|
||||
table_manager = {
|
||||
retention_deletes_enabled = false;
|
||||
retention_period = "0s";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
{ config, lib, tf, pkgs, sources, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ sources.nixos-mailserver.outPath ];
|
||||
|
||||
services.fail2ban.jails = {
|
||||
postfix = ''
|
||||
enabled = true
|
||||
filter = postfix
|
||||
maxretry = 3
|
||||
action = nftables-multiport[name=postfix, port=smtp, protocol=tcp]
|
||||
'';
|
||||
postfix-sasl = ''
|
||||
enabled = true
|
||||
filter = postfix-sasl
|
||||
port = postfix,imap3,imaps,pop3,pop3s
|
||||
maxretry = 3
|
||||
action = nftables-multiport[name=postfix, port=smtp, protocol=tcp]
|
||||
'';
|
||||
postfix-ddos = ''
|
||||
enabled = true
|
||||
filter = postfix-ddos
|
||||
maxretry = 3
|
||||
action = nftables-multiport[name=postfix, port=submission, protocol=tcp]
|
||||
bantime = 7200
|
||||
'';
|
||||
};
|
||||
|
||||
environment.etc."fail2ban/filter.d/postfix-sasl.conf" = {
|
||||
enable = true;
|
||||
text = ''
|
||||
# Fail2Ban filter for postfix authentication failures
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
[Definition]
|
||||
daemon = postfix/smtpd
|
||||
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/]*={0,2})?\s*$
|
||||
'';
|
||||
};
|
||||
|
||||
environment.etc."fail2ban/filter.d/postfix-ddos.conf" = {
|
||||
enable = true;
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = lost connection after EHLO from \S+\[<HOST>\]
|
||||
'';
|
||||
};
|
||||
|
||||
deploy.tf.variables.domainkey_kitty = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/domainkey-kitty";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_mx = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
mx = {
|
||||
priority = 10;
|
||||
target = "athame.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_spf = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
txt.value = "v=spf1 ip4:168.119.126.111 ip6:${
|
||||
(head config.networking.interfaces.enp1s0.ipv6.addresses).address
|
||||
} -all";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_dmarc = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "_dmarc";
|
||||
txt.value = "v=DMARC1; p=none";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_domainkey = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "mail._domainkey";
|
||||
txt.value = tf.variables.domainkey_kitty.ref;
|
||||
};
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
fqdn = "athame.kittywit.ch";
|
||||
domains = [ "kittywit.ch" "dork.dev" ];
|
||||
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
|
||||
# down nginx and opens port 80.
|
||||
certificateScheme = 3;
|
||||
|
||||
# Enable IMAP and POP3
|
||||
enableImap = true;
|
||||
enablePop3 = true;
|
||||
enableImapSsl = true;
|
||||
enablePop3Ssl = true;
|
||||
|
||||
# Enable the ManageSieve protocol
|
||||
enableManageSieve = true;
|
||||
|
||||
# whether to scan inbound emails for viruses (note that this requires at least
|
||||
# 1 Gb RAM for the server. Without virus scanning 256 MB RAM should be plenty)
|
||||
virusScanning = false;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
environment.systemPackages = [ pkgs.mx-puppet-discord pkgs.mautrix-whatsapp ];
|
||||
|
||||
services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||
TEMPLATE template0
|
||||
LC_COLLATE = "C"
|
||||
LC_CTYPE = "C";
|
||||
'';
|
||||
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
max_upload_size = "512M";
|
||||
server_name = "kittywit.ch";
|
||||
app_service_config_files = [
|
||||
"/var/lib/matrix-synapse/telegram-registration.yaml"
|
||||
"/var/lib/matrix-synapse/discord-registration.yaml"
|
||||
"/var/lib/matrix-synapse/whatsapp-registration.yaml"
|
||||
];
|
||||
rc_messages_per_second = mkDefault "0.1";
|
||||
rc_message_burst_count = mkDefault "25.0";
|
||||
url_preview_enabled = mkDefault true;
|
||||
enable_registration = mkDefault false;
|
||||
enable_metrics = mkDefault false;
|
||||
report_stats = mkDefault false;
|
||||
dynamic_thumbnails = mkDefault true;
|
||||
allow_guest_access = mkDefault true;
|
||||
extraConfig = ''
|
||||
suppress_key_server_warning: true
|
||||
'';
|
||||
listeners = [{
|
||||
port = 8008;
|
||||
bind_address = "::1";
|
||||
type = "http";
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
resources = [{
|
||||
names = [ "client" "federation" ];
|
||||
compress = false;
|
||||
}];
|
||||
}];
|
||||
};
|
||||
|
||||
services.mautrix-telegram = {
|
||||
enable = true;
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://localhost:8008";
|
||||
domain = "kittywit.ch";
|
||||
};
|
||||
appservice = {
|
||||
provisioning.enabled = false;
|
||||
id = "telegram";
|
||||
public = {
|
||||
enabled = false;
|
||||
prefix = "/public";
|
||||
external = "https://kittywit.ch/public";
|
||||
};
|
||||
};
|
||||
bridge = {
|
||||
relaybot.authless_portals = false;
|
||||
permissions = {
|
||||
"@kat:kittywit.ch" = "admin";
|
||||
"kittywit.ch" = "full";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.mx-puppet-discord = {
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
"${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -c /var/lib/mx-puppet-discord/config.yaml -f /var/lib/mx-puppet-discord/discord-registration.yaml";
|
||||
WorkingDirectory = "/var/lib/mx-puppet-discord";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "mx-puppet-discord";
|
||||
UMask = 27;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
};
|
||||
requisite = [ "matrix-synapse.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
};
|
||||
|
||||
systemd.services.mautrix-whatsapp = {
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
"${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp -c /var/lib/mautrix-whatsapp/config.yaml -r /var/lib/mautrix-whatsapp/registration.yaml";
|
||||
WorkingDirectory = "/var/lib/mautrix-whatsapp";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "mautrix-whatsapp";
|
||||
UMask = 27;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
};
|
||||
requisite = [ "matrix-synapse.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."kittywit.ch" = {
|
||||
# allegedly fixes https://github.com/poljar/weechat-matrix/issues/240
|
||||
extraConfig = ''
|
||||
keepalive_requests 100000;
|
||||
'';
|
||||
|
||||
locations = {
|
||||
"/_matrix" = { proxyPass = "http://[::1]:8008"; };
|
||||
"= /.well-known/matrix/server".extraConfig =
|
||||
let server = { "m.server" = "kittywit.ch:443"; };
|
||||
in
|
||||
''
|
||||
add_header Content-Type application/json;
|
||||
return 200 '${builtins.toJSON server}';
|
||||
'';
|
||||
"= /.well-known/matrix/client".extraConfig =
|
||||
let
|
||||
client = {
|
||||
"m.homeserver" = { "base_url" = "https://kittywit.ch"; };
|
||||
"m.identity_server" = { "base_url" = "https://vector.im"; };
|
||||
};
|
||||
in
|
||||
''
|
||||
add_header Content-Type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '${builtins.toJSON client}';
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ports = singleton 64738;
|
||||
kw.fw.public.udp.ports = singleton 64738;
|
||||
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
hostName = "voice.kittywit.ch";
|
||||
bandwidth = 130000;
|
||||
welcometext = "mew!";
|
||||
extraConfig = ''
|
||||
sslCert=/var/lib/acme/voice.kittywit.ch/fullchain.pem
|
||||
sslKey=/var/lib/acme/voice.kittywit.ch/key.pem
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."voice.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
users.groups."voice-cert".members = [ "nginx" "murmur" ];
|
||||
|
||||
security.acme.certs = { "voice.kittywit.ch" = { group = "voice-cert"; }; };
|
||||
|
||||
deploy.tf.dns.records.kittywitch_voice = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "voice";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_voice_tcp = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "mumble";
|
||||
proto = "tcp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 64738;
|
||||
target = "voice.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_voice_udp = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "mumble";
|
||||
proto = "udp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 64738;
|
||||
target = "voice.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = [ 19999 ];
|
||||
|
||||
services.netdata = { enable = true; };
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts = {
|
||||
"${config.networking.hostName}.net.kittywit.ch" = {
|
||||
useACMEHost = "${config.networking.hostName}.net.kittywit.ch";
|
||||
forceSSL = true;
|
||||
locations = { "/netdata" = { proxyPass = "http://[::1]:19999/"; }; };
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
{ config, lib, pkgs, tf, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
secrets.files.dns_creds = {
|
||||
text = ''
|
||||
RFC2136_NAMESERVER='ns1.as207960.net'
|
||||
RFC2136_TSIG_ALGORITHM='hmac-sha512.'
|
||||
RFC2136_TSIG_KEY='${tf.variables.glauca_key.ref}'
|
||||
RFC2136_TSIG_SECRET='${tf.variables.glauca_secret.ref}'
|
||||
'';
|
||||
};
|
||||
|
||||
kw.fw.public.tcp.ports = [ 443 80 ];
|
||||
kw.fw.private.tcp.ports = [ 443 80 ];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
commonHttpConfig = ''
|
||||
map $scheme $hsts_header {
|
||||
https "max-age=31536000; includeSubdomains; preload";
|
||||
}
|
||||
add_header Strict-Transport-Security $hsts_header;
|
||||
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
|
||||
add_header 'Referrer-Policy' 'origin-when-cross-origin';
|
||||
#add_header X-Frame-Options DENY;
|
||||
#add_header X-Content-Type-Options nosniff;
|
||||
#add_header X-XSS-Protection "1; mode=block";
|
||||
#proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
|
||||
'';
|
||||
clientMaxBodySize = "512m";
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
email = "acme@kittywit.ch";
|
||||
acceptTerms = true;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = [ 9002 ];
|
||||
|
||||
services.prometheus = {
|
||||
exporters = {
|
||||
node = {
|
||||
enable = true;
|
||||
enabledCollectors = [ "systemd" ];
|
||||
port = 9002;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.postgresql.enable = true;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
{ config, hosts, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
prom_configs =
|
||||
(mapAttrs (hostName: host: host.config.services.prometheus.exporters.node)
|
||||
(filterAttrs
|
||||
(_: host: host.config.services.prometheus.exporters.node.enable)
|
||||
hosts));
|
||||
nd_configs = (mapAttrs (hostName: host: host.config.services.netdata)
|
||||
(filterAttrs (_: host: host.config.services.netdata.enable) hosts));
|
||||
in
|
||||
{
|
||||
services.prometheus = {
|
||||
enable = true;
|
||||
scrapeConfigs = [
|
||||
{
|
||||
job_name = "boline";
|
||||
static_configs = [{ targets = [ "boline.net.kittywit.ch:8002" ]; }];
|
||||
}
|
||||
{
|
||||
job_name = "samhain-vm";
|
||||
metrics_path = "/metrics";
|
||||
static_configs = [{ targets = [ "samhain.net.kittywit.ch:10445" ]; }];
|
||||
}
|
||||
] ++ mapAttrsToList
|
||||
(hostName: prom: {
|
||||
job_name = "${hostName}-nd";
|
||||
metrics_path = "/api/v1/allmetrics";
|
||||
honor_labels = true;
|
||||
params = { format = [ "prometheus" ]; };
|
||||
static_configs = [{ targets = [ "${hostName}.net.kittywit.ch:19999" ]; }];
|
||||
})
|
||||
nd_configs ++ mapAttrsToList
|
||||
(hostName: prom: {
|
||||
job_name = hostName;
|
||||
static_configs = [{
|
||||
targets = [ "${hostName}.net.kittywit.ch:${toString prom.port}" ];
|
||||
}];
|
||||
})
|
||||
prom_configs;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
promtail_config = pkgs.writeText "prom-config.json" (builtins.toJSON {
|
||||
clients =
|
||||
[{ url = "http://athame.net.kittywit.ch:3100/loki/api/v1/push"; }];
|
||||
positions = { filename = "/tmp/positions.yaml"; };
|
||||
scrape_configs = [{
|
||||
job_name = "journal";
|
||||
journal = {
|
||||
labels = {
|
||||
host = config.networking.hostName;
|
||||
job = "systemd-journal";
|
||||
};
|
||||
max_age = "12h";
|
||||
};
|
||||
relabel_configs = [{
|
||||
source_labels = [ "__journal__systemd_unit" ];
|
||||
target_label = "unit";
|
||||
}];
|
||||
}];
|
||||
server = {
|
||||
grpc_listen_port = 0;
|
||||
http_listen_port = 28183;
|
||||
};
|
||||
});
|
||||
in
|
||||
{
|
||||
systemd.services.promtail = {
|
||||
description = "Promtail service for Loki";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.grafana-loki}/bin/promtail --config.file ${promtail_config}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.restic.backups.tardis = {
|
||||
passwordFile = "/etc/restic/system";
|
||||
paths = [ "/home" "/var/lib" ];
|
||||
pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12" ];
|
||||
repository = "";
|
||||
};
|
||||
systemd.services."restic-backups-tardis".environment.RESTIC_REPOSITORY_FILE =
|
||||
"/etc/restic/system.repo";
|
||||
services.postgresqlBackup = {
|
||||
enable = config.services.postgresql.enable;
|
||||
backupAll = true;
|
||||
startAt = "*-*-* 23:45:00";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{ config, lib, pkgs, tf, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
users.users.syncplay = { isSystemUser = true; };
|
||||
|
||||
users.groups."sync-cert".members = [ "nginx" "syncplay" ];
|
||||
security.acme = { certs."sync.kittywit.ch" = { group = "sync-cert"; }; };
|
||||
|
||||
kw.fw.public.tcp.ports = singleton 8999;
|
||||
|
||||
services.nginx.virtualHosts."sync.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_sync = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "sync";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
|
||||
deploy.tf.variables.syncplay_pass = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/syncplay-server -f password";
|
||||
};
|
||||
|
||||
deploy.tf.variables.syncplay_salt = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/syncplay-salt -f password";
|
||||
};
|
||||
|
||||
secrets.files.syncplay-env = {
|
||||
text = ''
|
||||
SYNCPLAY_PASSWORD=${tf.variables.syncplay_pass.ref}
|
||||
SYNCPLAY_SALT=${tf.variables.syncplay_salt.ref}
|
||||
'';
|
||||
owner = "syncplay";
|
||||
group = "sync-cert";
|
||||
};
|
||||
|
||||
systemd.services.syncplay = {
|
||||
description = "Syncplay Service";
|
||||
wantedBy = singleton "multi-user.target";
|
||||
after = singleton "network-online.target";
|
||||
|
||||
serviceConfig = {
|
||||
EnvironmentFile = config.secrets.files.syncplay-env.path;
|
||||
ExecStart =
|
||||
"${pkgs.syncplay}/bin/syncplay-server --port 8999 --tls /var/lib/acme/sync.kittywit.ch/ --disable-ready";
|
||||
User = "syncplay";
|
||||
Group = "sync-cert";
|
||||
};
|
||||
};
|
||||
|
||||
security.acme.certs."sync.kittywit.ch".postRun = ''
|
||||
cp key.pem privkey.pem
|
||||
chown acme:voice-cert privkey.pem'';
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ports = singleton 53589;
|
||||
|
||||
services.taskserver = {
|
||||
enable = true;
|
||||
fqdn = "kittywit.ch";
|
||||
listenHost = "::";
|
||||
organisations.kittywitch.users = singleton "kat";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.nginx.virtualHosts."irc.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/" = { root = pkgs.glowing-bear; };
|
||||
"^~ /weechat" = {
|
||||
proxyPass = "http://127.0.0.1:9000";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_irc = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "irc";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ports = [ 5000 5222 5223 5269 580 5281 5347 5582 ];
|
||||
|
||||
services.postgresql = {
|
||||
ensureDatabases = [ "prosody" ];
|
||||
ensureUsers = [{
|
||||
name = "prosody";
|
||||
ensurePermissions."DATABASE prosody" = "ALL PRIVILEGES";
|
||||
}];
|
||||
};
|
||||
|
||||
|
||||
services.prosody = {
|
||||
enable = true;
|
||||
ssl.cert = "/var/lib/acme/prosody/fullchain.pem";
|
||||
ssl.key = "/var/lib/acme/prosody/key.pem";
|
||||
admins = [ "kat@kittywit.ch" ];
|
||||
package =
|
||||
let
|
||||
package = pkgs.prosody.override (old: {
|
||||
withExtraLibs = old.withExtraLibs ++ singleton pkgs.luaPackages.luadbi-postgresql;
|
||||
}); in
|
||||
package;
|
||||
extraConfig = ''
|
||||
legacy_ssl_ports = { 5223 }
|
||||
storage = "sql"
|
||||
sql = {
|
||||
driver = "PostgreSQL";
|
||||
host = "";
|
||||
database = "prosody";
|
||||
username = "prosody";
|
||||
}
|
||||
'';
|
||||
virtualHosts = {
|
||||
"xmpp.kittywit.ch" = {
|
||||
domain = "kittywit.ch";
|
||||
enabled = true;
|
||||
ssl.cert = "/var/lib/acme/prosody/fullchain.pem";
|
||||
ssl.key = "/var/lib/acme/prosody/key.pem";
|
||||
};
|
||||
};
|
||||
muc = [{ domain = "conference.kittywit.ch"; }];
|
||||
uploadHttp = { domain = "upload.kittywit.ch"; };
|
||||
};
|
||||
|
||||
security.acme.certs.prosody = {
|
||||
domain = "xmpp.kittywit.ch";
|
||||
group = "prosody";
|
||||
dnsProvider = "rfc2136";
|
||||
credentialsFile = config.secrets.files.dns_creds.path;
|
||||
postRun = "systemctl restart prosody";
|
||||
extraDomainNames =
|
||||
[ "kittywit.ch" "upload.kittywit.ch" "conference.kittywit.ch" ];
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_xmpp = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "xmpp";
|
||||
a.address = "168.119.126.111";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_xmpp_v6 = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "xmpp";
|
||||
aaaa.address =
|
||||
(lib.head config.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_upload = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "upload";
|
||||
cname.target = "xmpp.kittywit.ch.";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_conference = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "conference";
|
||||
cname.target = "xmpp.kittywit.ch.";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_xmpp_muc = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "conference";
|
||||
srv = {
|
||||
service = "xmpp-server";
|
||||
proto = "tcp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 5269;
|
||||
target = "xmpp.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_xmpp_client = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "xmpp-client";
|
||||
proto = "tcp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 5222;
|
||||
target = "xmpp.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_xmpps_client = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "xmpps-client";
|
||||
proto = "tcp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 5223;
|
||||
target = "xmpp.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_xmpp_server = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "xmpp-server";
|
||||
proto = "tcp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 5269;
|
||||
target = "xmpp.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"upload.kittywit.ch" = {
|
||||
useACMEHost = "prosody";
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
"conference.kittywit.ch" = {
|
||||
useACMEHost = "prosody";
|
||||
forceSSL = true;
|
||||
};
|
||||
};
|
||||
users.users.nginx.extraGroups = [ "prosody" ];
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.zfs = {
|
||||
autoScrub.enable = true;
|
||||
autoSnapshot = {
|
||||
enable = true;
|
||||
frequent = 1;
|
||||
daily = 7;
|
||||
weekly = 1;
|
||||
monthly = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.znc = {
|
||||
enable = true;
|
||||
mutable = false;
|
||||
useLegacyConfig = false;
|
||||
openFirewall = false;
|
||||
modulePackages = with pkgs.zncModules; [
|
||||
clientbuffer
|
||||
clientaway
|
||||
];
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue