Compare commits
3 Commits
7570974a67
...
56a34de0cb
Author | SHA1 | Date | |
---|---|---|---|
56a34de0cb | |||
f8ab76d163 | |||
c2786dbeb3 |
@ -7,6 +7,7 @@
|
|||||||
../../configuration/proxmox-vm
|
../../configuration/proxmox-vm
|
||||||
|
|
||||||
./backup.nix
|
./backup.nix
|
||||||
|
./restic-server.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.loader.grub.enable = true;
|
boot.loader.grub.enable = true;
|
||||||
@ -20,6 +21,10 @@
|
|||||||
networking.defaultGateway6 = { address = "2001:638:904:ffcb::1"; interface = "ens18"; };
|
networking.defaultGateway6 = { address = "2001:638:904:ffcb::1"; interface = "ens18"; };
|
||||||
networking.nameservers = [ "2001:638:904:ffcc::3" "2001:638:904:ffcc::4" "141.24.40.3" "141.24.40.4" ];
|
networking.nameservers = [ "2001:638:904:ffcc::3" "2001:638:904:ffcc::4" "141.24.40.3" "141.24.40.4" ];
|
||||||
|
|
||||||
|
services.nginx.enable = true;
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
clerie.monitoring = {
|
clerie.monitoring = {
|
||||||
enable = true;
|
enable = true;
|
||||||
id = "205";
|
id = "205";
|
||||||
|
21
hosts/backup-4/restic-server.nix
Normal file
21
hosts/backup-4/restic-server.nix
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.restic.server = {
|
||||||
|
enable = true;
|
||||||
|
privateRepos = true;
|
||||||
|
dataDir = "/mnt/backup-4/magenta";
|
||||||
|
listenAddress = "[::1]:43242";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."magenta.backup.clerie.de" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://[::1]:43242/";
|
||||||
|
extraConfig = ''
|
||||||
|
client_max_body_size 10G;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -5,6 +5,8 @@
|
|||||||
[
|
[
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
../../configuration/proxmox-vm
|
../../configuration/proxmox-vm
|
||||||
|
|
||||||
|
./restic-server.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.loader.grub.enable = true;
|
boot.loader.grub.enable = true;
|
||||||
@ -20,6 +22,10 @@
|
|||||||
networking.defaultGateway6 = { address = "2001:638:904:ffc1::1"; interface = "ens18"; };
|
networking.defaultGateway6 = { address = "2001:638:904:ffc1::1"; interface = "ens18"; };
|
||||||
networking.nameservers = [ "2001:638:904:ffcc::3" "2001:638:904:ffcc::4" "141.24.40.3" "141.24.40.4" ];
|
networking.nameservers = [ "2001:638:904:ffcc::3" "2001:638:904:ffcc::4" "141.24.40.3" "141.24.40.4" ];
|
||||||
|
|
||||||
|
services.nginx.enable = true;
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
services.borgbackup.repos = {
|
services.borgbackup.repos = {
|
||||||
#clerie = {
|
#clerie = {
|
||||||
# authorizedKeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnUBblmmVoMMBftn4EnwnzqR12m9zill51LpO124hHb10K2rqxNoq8tYSc2pMkV/3briZovffpe5SzB+m2MnXbtOBstIEXkrPZQ78vaZ/nLh7+eWg30lCmMPwjf2wIjlTXkcbxbsi7FbPW7FsolGkU/0mqGhqK1Xft/g7SnCXIoGPSSrHMXEv5dPPofCa1Z0Un+98wQTVfOSKek6TnIsfLbG01UFQVkN7afE4dqSmMiWwEm2PK9l+OiBA2/QzDpbtu9wsfTol4c192vFEWR9crB2YZ1JlMbjVWHjYmB7NFsS0A6lUOikss0Y+LUWS2/QuM/kqybSo4rasZMAIazM6D clerie" ];
|
# authorizedKeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnUBblmmVoMMBftn4EnwnzqR12m9zill51LpO124hHb10K2rqxNoq8tYSc2pMkV/3briZovffpe5SzB+m2MnXbtOBstIEXkrPZQ78vaZ/nLh7+eWg30lCmMPwjf2wIjlTXkcbxbsi7FbPW7FsolGkU/0mqGhqK1Xft/g7SnCXIoGPSSrHMXEv5dPPofCa1Z0Un+98wQTVfOSKek6TnIsfLbG01UFQVkN7afE4dqSmMiWwEm2PK9l+OiBA2/QzDpbtu9wsfTol4c192vFEWR9crB2YZ1JlMbjVWHjYmB7NFsS0A6lUOikss0Y+LUWS2/QuM/kqybSo4rasZMAIazM6D clerie" ];
|
||||||
|
21
hosts/clerie-backup/restic-server.nix
Normal file
21
hosts/clerie-backup/restic-server.nix
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.restic.server = {
|
||||||
|
enable = true;
|
||||||
|
privateRepos = true;
|
||||||
|
dataDir = "/mnt/clerie-backup/cyan";
|
||||||
|
listenAddress = "[::1]:43242";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."cyan.backup.clerie.de" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://[::1]:43242/";
|
||||||
|
extraConfig = ''
|
||||||
|
client_max_body_size 10G;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.nginx.virtualHosts = {
|
|
||||||
"bahnansagen.clerie.de" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/" = {
|
|
||||||
alias = "/data/bahnansagen/";
|
|
||||||
basicAuthFile = "/var/src/secrets/nginx/bahnansagen.htpasswd";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -5,10 +5,7 @@
|
|||||||
[
|
[
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
../../configuration/proxmox-vm
|
../../configuration/proxmox-vm
|
||||||
./bahnansagen.nix
|
|
||||||
./mixcloud.nix
|
./mixcloud.nix
|
||||||
./share.nix
|
|
||||||
./storage.nix
|
|
||||||
./syncthing.nix
|
./syncthing.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,321 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<title>storage.clerie.de</title>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: Roboto;
|
|
||||||
color: #222222;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
}
|
|
||||||
|
|
||||||
header > .title {
|
|
||||||
padding: 3em;
|
|
||||||
min-height: 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
header > .title > h1 {
|
|
||||||
color: #222222;
|
|
||||||
}
|
|
||||||
|
|
||||||
header > .menu {
|
|
||||||
padding: 1em 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
header > .menu > button,
|
|
||||||
header > .menu > input {
|
|
||||||
height: 3em;
|
|
||||||
min-width: 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
}
|
|
||||||
|
|
||||||
.listing {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listing-item {
|
|
||||||
padding: 1em 3em;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
min-height: 3em;
|
|
||||||
|
|
||||||
border-top-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
border-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listing-item:hover {
|
|
||||||
background-color: rgb(245, 245, 245);
|
|
||||||
}
|
|
||||||
|
|
||||||
.listing-item > .detail {
|
|
||||||
flex: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listing-item > .detail > a {
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.listing-item button {
|
|
||||||
height: 3em;
|
|
||||||
min-width: 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
button, input[type="file"] {
|
|
||||||
border-style: none;
|
|
||||||
background-color: transparent;
|
|
||||||
min-width: 3em;
|
|
||||||
height: 3em;
|
|
||||||
border-radius: 0.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
|
||||||
background-color: #DDDDDD;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
@keyframes spinner {
|
|
||||||
0% {
|
|
||||||
transform: translate3d(-50%, -50%, 0) rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translate3d(-50%, -50%, 0) rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.loading::before {
|
|
||||||
display: block;
|
|
||||||
animation: 1.5s linear infinite spinner;
|
|
||||||
animation-play-state: inherit;
|
|
||||||
border: solid 5px #cfd0d1;
|
|
||||||
border-bottom-color: #1c87c9;
|
|
||||||
border-radius: 50%;
|
|
||||||
content: "";
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
transform: translate3d(-50%, -50%, 0);
|
|
||||||
will-change: transform;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<div class="title">
|
|
||||||
<h1 id="path"></h1>
|
|
||||||
</div>
|
|
||||||
<div class="menu">
|
|
||||||
<button onclick="createDirectoryButton();">📁 +</button>
|
|
||||||
<input id="files" type="file" multiple> <button onclick="uploadFilesButton();">⭫</button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<div id="listing"></div>
|
|
||||||
</main>
|
|
||||||
<script>
|
|
||||||
let path_field = document.getElementById("path");
|
|
||||||
let listing_field = document.getElementById("listing");
|
|
||||||
|
|
||||||
let base_path = "/_";
|
|
||||||
|
|
||||||
if (window.location.hash === "") {
|
|
||||||
window.location.hash = "#/";
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_path = window.location.hash.substring(1);
|
|
||||||
|
|
||||||
function deleteFile(path) {
|
|
||||||
fetch(base_path + path, {
|
|
||||||
method: 'DELETE',
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Removing file failed");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
listFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteFileButton(path) {
|
|
||||||
if (confirm("Are you sure you wanna delete " + path + "?")) {
|
|
||||||
deleteFile(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDirectory(path) {
|
|
||||||
fetch(base_path + path, {
|
|
||||||
method: 'MKCOL',
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Creating directory failed");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
listFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDirectoryButton() {
|
|
||||||
let dir_name = prompt("Directory name");
|
|
||||||
if (dir_name !== null) {
|
|
||||||
createDirectory(current_path + dir_name + "/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function uploadFile(path, file) {
|
|
||||||
|
|
||||||
fetch(base_path + path, {
|
|
||||||
method: 'PUT',
|
|
||||||
body: file,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Upload failed");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
listFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function uploadFilesButton() {
|
|
||||||
let files = document.getElementById("files").files;
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
|
||||||
uploadFile(current_path + files[i].name, files[i]);
|
|
||||||
}
|
|
||||||
document.getElementById("files").value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveFile(old_path, new_path) {
|
|
||||||
fetch(base_path + old_path, {
|
|
||||||
method: 'MOVE',
|
|
||||||
headers: {
|
|
||||||
'Destination': base_path + new_path,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Rename file failed");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
listFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveFileButton(path) {
|
|
||||||
let new_path = prompt("New file path", path);
|
|
||||||
moveFile(path, new_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renameFileButton(path) {
|
|
||||||
let new_name = prompt("New file name");
|
|
||||||
moveFile(path, current_path + new_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyFile(path, new_path) {
|
|
||||||
fetch(base_path + path, {
|
|
||||||
method: 'COPY',
|
|
||||||
headers: {
|
|
||||||
'Destination': base_path + new_path,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Copy file failed");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
listFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function duplicateFileButton(path) {
|
|
||||||
let new_path = prompt("New file path", path);
|
|
||||||
copyFile(path, new_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
function listFiles() {
|
|
||||||
listing_field.innerHTML = '<div class="loading"></div>';
|
|
||||||
|
|
||||||
path_field.innerHTML = '<a href="#/">⌂</a>';
|
|
||||||
|
|
||||||
let path_blocks = current_path.split('/').slice(1);
|
|
||||||
for (let i = 0; i < path_blocks.length; i++) {
|
|
||||||
path_field.innerHTML += ' / <a href="#/' + path_blocks.slice(0, i+1).join('/') + '/">' + path_blocks[i] + '</a>';
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch(base_path + current_path)
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Can't fetch directory");
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then((listing) => {
|
|
||||||
console.log(listing);
|
|
||||||
let out = '<div class="listing">';
|
|
||||||
for (let i = 0; i < listing.length; i++) {
|
|
||||||
let listing_path = current_path + encodeURIComponent(listing[i]["name"]);
|
|
||||||
let listing_link = "#";
|
|
||||||
let listing_icon = "";
|
|
||||||
if (listing[i]["type"] === "directory") {
|
|
||||||
listing_path += '/';
|
|
||||||
listing_link = '#' + listing_path;
|
|
||||||
listing_icon = "📁";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
listing_link = base_path + listing_path;
|
|
||||||
}
|
|
||||||
out += '<div class="listing-item">'
|
|
||||||
+ '<div class="detail">'
|
|
||||||
+ '<a href="' + listing_link + '">' + listing_icon + " " + listing[i]["name"] + '</a>'
|
|
||||||
+ '</div>'
|
|
||||||
+ '<div class="options">'
|
|
||||||
+ '<button onclick="renameFileButton(\'' + listing_path + '\');" alt="rename">✎</button>'
|
|
||||||
+ '<button onclick="duplicateFileButton(\'' + listing_path + '\');">●●</button>'
|
|
||||||
+ '<button onclick="moveFileButton(\'' + listing_path + '\');">⇨</button>'
|
|
||||||
+ '<button onclick="deleteFileButton(\'' + listing_path + '\');">❌</button>'
|
|
||||||
+ '</div>'
|
|
||||||
+ '</div>';
|
|
||||||
}
|
|
||||||
out += '</div>';
|
|
||||||
listing_field.innerHTML = out;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
listFiles();
|
|
||||||
|
|
||||||
window.onhashchange = () => {
|
|
||||||
current_path = window.location.hash.substring(1);
|
|
||||||
listFiles();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -58,6 +58,14 @@ in {
|
|||||||
autoindex_exact_size off;
|
autoindex_exact_size off;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
locations."/media/" = {
|
||||||
|
alias = "/data/media/";
|
||||||
|
basicAuthFile = "/var/src/secrets/nginx/mixcloud.htpasswd";
|
||||||
|
extraConfig = ''
|
||||||
|
autoindex on;
|
||||||
|
autoindex_exact_size off;
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.nginx.virtualHosts = {
|
|
||||||
"share.clerie.de" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
|
|
||||||
locations."~ \"/([0-9a-z]+)/\"" = {
|
|
||||||
root = "/data/share/";
|
|
||||||
extraConfig = ''
|
|
||||||
autoindex on;
|
|
||||||
autoindex_exact_size off;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.nginx.virtualHosts = {
|
|
||||||
"storage.clerie.de" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
|
|
||||||
basicAuthFile = "/var/src/secrets/nginx/storage.htpasswd";
|
|
||||||
|
|
||||||
locations."= /" = {
|
|
||||||
alias = "${./filemanager}/";
|
|
||||||
extraConfig = ''
|
|
||||||
try_files index.html =404;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
locations."/_/" = {
|
|
||||||
alias = "/data/";
|
|
||||||
extraConfig = ''
|
|
||||||
autoindex on;
|
|
||||||
autoindex_format json;
|
|
||||||
|
|
||||||
client_body_temp_path /data;
|
|
||||||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
|
||||||
create_full_put_path on;
|
|
||||||
dav_access group:rw all:r;
|
|
||||||
client_max_body_size 1G;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.nginx.serviceConfig = {
|
|
||||||
ReadWritePaths = "/data";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user