Compare commits
5 Commits
main
...
cache-bett
Author | SHA1 | Date |
---|---|---|
Cadey Ratio | 89fbb37e7c | |
Cadey Ratio | 4ba4a83417 | |
Cadey Ratio | ef3b80ede3 | |
Cadey Ratio | 52779efa04 | |
Cadey Ratio | 31cad90e0a |
|
@ -36,6 +36,12 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
|
@ -47,12 +53,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.9.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c96c3d1062ea7101741480185a6a1275eab01cbe8b20e378d1311bc056d2e08"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
checksum = "aba2d96b8c8b5e656ad7ffb0d09f57772f10a1db74c8d23fca0ec695b38a4047"
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
|
@ -78,27 +81,6 @@ version = "0.5.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3670df70cbc01729f901f94c887814b3c68db038aad1329a418bae178bc5295c"
|
||||
dependencies = [
|
||||
"async-stream-impl",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream-impl"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3548b8efc9f8e8a5a0a2808c5bd8451a9031b9e5b879a79590304ae928b0a70"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -230,21 +212,6 @@ version = "1.0.66"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
|
||||
[[package]]
|
||||
name = "cfcache"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"eyre",
|
||||
"kankyo",
|
||||
"reqwest 0.11.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio 1.1.0",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
|
@ -374,9 +341,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dhall"
|
||||
version = "0.9.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7930c7ac2b3989a07a2a3400bf9f4bc1c65074f330e3ff22b372a4d386fabd0"
|
||||
checksum = "a8e2aa2abb16c2ef064fbc45f5163be5c5ff990e8584e54fb1c8f6e318107289"
|
||||
dependencies = [
|
||||
"abnf_to_pest",
|
||||
"annotate-snippets",
|
||||
|
@ -389,11 +356,12 @@ dependencies = [
|
|||
"pest_consume",
|
||||
"pest_generator",
|
||||
"quote",
|
||||
"reqwest 0.10.10",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"sha2",
|
||||
"url",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -507,18 +475,6 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crc32fast",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -709,28 +665,8 @@ dependencies = [
|
|||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio 0.2.24",
|
||||
"tokio-util 0.3.1",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b67e66362108efccd8ac053abafc8b7a8d86a37e6e48fc4f6f7485eb5e9e6a5"
|
||||
dependencies = [
|
||||
"bytes 1.0.0",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio 1.1.0",
|
||||
"tokio-util 0.6.2",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
]
|
||||
|
@ -808,16 +744,6 @@ dependencies = [
|
|||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994"
|
||||
dependencies = [
|
||||
"bytes 1.0.0",
|
||||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.3.4"
|
||||
|
@ -849,39 +775,15 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.2.7",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body 0.3.1",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project 1.0.4",
|
||||
"socket2",
|
||||
"tokio 0.2.24",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12219dc884514cb4a6a03737f4413c0e01c23a1b059b0156004b23f1e19dccbe"
|
||||
dependencies = [
|
||||
"bytes 1.0.0",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.3.0",
|
||||
"http",
|
||||
"http-body 0.4.0",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project 1.0.4",
|
||||
"socket2",
|
||||
"tokio 1.1.0",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
|
@ -894,25 +796,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"hyper 0.13.9",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio 0.2.24",
|
||||
"tokio",
|
||||
"tokio-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes 1.0.0",
|
||||
"hyper 0.14.2",
|
||||
"native-tls",
|
||||
"tokio 1.1.0",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.0"
|
||||
|
@ -942,11 +831,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "input_buffer"
|
||||
version = "0.4.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413"
|
||||
checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754"
|
||||
dependencies = [
|
||||
"bytes 1.0.0",
|
||||
"bytes 0.5.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1048,6 +937,24 @@ version = "0.2.82"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389de7875e06476365974da3e7ff85d55f1972188ccd9f6020dd7c8156e17914"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"crc32fast",
|
||||
"libflate_lz77",
|
||||
"rle-decode-fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate_lz77"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3286f09f7d4926fc486334f28d8d2e6ebe4f7f9994494b6dab27ddfad2c9b11b"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
|
@ -1065,9 +972,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.13"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
|
||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
]
|
||||
|
@ -1113,11 +1020,11 @@ dependencies = [
|
|||
"color-eyre",
|
||||
"envy",
|
||||
"pretty_env_logger",
|
||||
"reqwest 0.11.0",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio 1.1.0",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
]
|
||||
|
@ -1161,25 +1068,12 @@ dependencies = [
|
|||
"kernel32-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"miow 0.2.2",
|
||||
"miow",
|
||||
"net2",
|
||||
"slab",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e50ae3f04d169fcc9bde0b547d1c205219b7157e07ded9c5aff03e0637cb3ed7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow 0.3.6",
|
||||
"ntapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.2.2"
|
||||
|
@ -1192,16 +1086,6 @@ dependencies = [
|
|||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multipart"
|
||||
version = "0.17.1"
|
||||
|
@ -1260,15 +1144,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -1393,11 +1268,11 @@ dependencies = [
|
|||
"chrono",
|
||||
"envy",
|
||||
"pretty_env_logger",
|
||||
"reqwest 0.11.0",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio 1.1.0",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
]
|
||||
|
@ -1481,7 +1356,7 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83abebdb324c30f176d449513f0134bafbf976d5279c6554742599e3996d1629"
|
||||
dependencies = [
|
||||
"rand 0.8.2",
|
||||
"rand 0.8.1",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
|
@ -1593,25 +1468,25 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "procfs"
|
||||
version = "0.9.1"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab8809e0c18450a2db0f236d2a44ec0b4c1412d0eb936233579f0990faa5d5cd"
|
||||
checksum = "c4a336c8310f4955f343935b9c11a30254d1ad8fad98ec257a4407a061a6fd49"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"flate2",
|
||||
"hex",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libflate",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prometheus"
|
||||
version = "0.11.0"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8425533e7122f0c3cc7a37e6244b16ad3a2cc32ae7ac6276e2a75da0d9c200d"
|
||||
checksum = "30d70cf4412832bcac9cffe27906f4a66e450d323525e977168c70d1b36120ae"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 0.1.10",
|
||||
"fnv",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
|
@ -1651,9 +1526,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.2"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e"
|
||||
checksum = "c24fcd450d3fa2b592732565aa4f17a27a61c65ece4726353e000939b0edee34"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.0",
|
||||
|
@ -1772,9 +1647,9 @@ dependencies = [
|
|||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body 0.3.1",
|
||||
"hyper 0.13.9",
|
||||
"hyper-tls 0.4.3",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
|
@ -1786,8 +1661,8 @@ dependencies = [
|
|||
"pin-project-lite 0.2.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio 0.2.24",
|
||||
"serde_urlencoded 0.7.0",
|
||||
"tokio",
|
||||
"tokio-tls",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
|
@ -1797,45 +1672,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.0"
|
||||
name = "rle-decode-fast"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd281b1030aa675fb90aa994d07187645bb3c8fc756ca766e7c3070b439de9de"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes 1.0.0",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body 0.4.0",
|
||||
"hyper 0.14.2",
|
||||
"hyper-tls 0.5.0",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio 1.1.0",
|
||||
"tokio-native-tls",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"winreg",
|
||||
]
|
||||
checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
||||
|
||||
[[package]]
|
||||
name = "ructe"
|
||||
version = "0.13.0"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3507c22423c8be907293f0aa684b08ac62efb20e0768639fdfbce833481fd30"
|
||||
checksum = "1b8ffc645837eab09b6cbb6772d18897c6309753254592e149b40ff7fb113c01"
|
||||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"bytecount",
|
||||
|
@ -1863,6 +1709,15 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.19"
|
||||
|
@ -1916,28 +1771,29 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.120"
|
||||
version = "1.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "166b2349061381baf54a58e4b13c89369feb0ef2eaa57198899e2312aac30aab"
|
||||
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_cbor"
|
||||
version = "0.11.1"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
|
||||
checksum = "45cd6d95391b16cd57e88b68be41d504183b7faae22030c0cc3b3f73dd57b2fd"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"half",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.120"
|
||||
version = "1.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca2a8cb5805ce9e3b95435e3765b7b553cecc762d938d409434338386cb5775"
|
||||
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1946,9 +1802,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_dhall"
|
||||
version = "0.9.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f80d945a711c648e559c4d39832379f36a303d393fca4719080de51701266f38"
|
||||
checksum = "313ac1225c35cd2760b4124d39fa4df19b4a5e29edd55a3eb3fc0b01940f8707"
|
||||
dependencies = [
|
||||
"dhall",
|
||||
"dhall_proc_macros",
|
||||
|
@ -1968,6 +1824,18 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"itoa",
|
||||
"serde",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.0"
|
||||
|
@ -2045,15 +1913,6 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sitemap"
|
||||
version = "0.4.1"
|
||||
|
@ -2211,64 +2070,24 @@ dependencies = [
|
|||
"iovec",
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"mio 0.6.23",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite 0.1.11",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8efab2086f17abcddb8f756117665c958feee6b2e39974c2f1600592ab3a4195"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes 1.0.0",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio 0.7.7",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"pin-project-lite 0.2.3",
|
||||
"signal-hook-registry",
|
||||
"tokio-macros",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.0.0"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42517d2975ca3114b22a16192634e8241dc5cc1f130be194645970cc1c371494"
|
||||
checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76066865172052eb8796c686f0b441a93df8b08d40a950b062ffb9a426f00edd"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite 0.2.3",
|
||||
"tokio 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tls"
|
||||
version = "0.3.1"
|
||||
|
@ -2276,19 +2095,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio 0.2.24",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.13.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b"
|
||||
checksum = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"pin-project 1.0.4",
|
||||
"tokio 1.1.0",
|
||||
"pin-project 0.4.27",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
|
@ -2303,23 +2122,7 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite 0.1.11",
|
||||
"tokio 0.2.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "feb971a26599ffd28066d387f109746df178eff14d5ea1e235015c5601967a4b"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"bytes 1.0.0",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite 0.2.3",
|
||||
"tokio 1.1.0",
|
||||
"tokio-stream",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2432,18 +2235,18 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
|||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.12.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24"
|
||||
checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"base64 0.12.3",
|
||||
"byteorder",
|
||||
"bytes 1.0.0",
|
||||
"bytes 0.5.6",
|
||||
"http",
|
||||
"httparse",
|
||||
"input_buffer",
|
||||
"log",
|
||||
"rand 0.8.2",
|
||||
"rand 0.7.3",
|
||||
"sha-1 0.9.2",
|
||||
"url",
|
||||
"utf-8",
|
||||
|
@ -2549,6 +2352,12 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlencoding"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593"
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.5"
|
||||
|
@ -2583,6 +2392,17 @@ version = "0.9.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi 0.3.9",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
|
@ -2595,32 +2415,30 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "warp"
|
||||
version = "0.3.0"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dafd0aac2818a94a34df0df1100a7356c493d8ede4393875fd0b5c51bb6bc80"
|
||||
checksum = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407"
|
||||
dependencies = [
|
||||
"bytes 1.0.0",
|
||||
"bytes 0.5.6",
|
||||
"futures",
|
||||
"headers",
|
||||
"http",
|
||||
"hyper 0.14.2",
|
||||
"hyper",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"multipart",
|
||||
"percent-encoding",
|
||||
"pin-project 1.0.4",
|
||||
"pin-project 0.4.27",
|
||||
"scoped-tls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio 1.1.0",
|
||||
"tokio-stream",
|
||||
"serde_urlencoded 0.6.1",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util 0.6.2",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2783,9 +2601,8 @@ checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
|||
|
||||
[[package]]
|
||||
name = "xesite"
|
||||
version = "2.2.0"
|
||||
version = "2.1.0"
|
||||
dependencies = [
|
||||
"cfcache",
|
||||
"chrono",
|
||||
"color-eyre",
|
||||
"comrak",
|
||||
|
@ -2793,7 +2610,7 @@ dependencies = [
|
|||
"eyre",
|
||||
"glob",
|
||||
"go_vanity",
|
||||
"hyper 0.14.2",
|
||||
"hyper",
|
||||
"jsonfeed",
|
||||
"kankyo",
|
||||
"lazy_static",
|
||||
|
@ -2804,9 +2621,8 @@ dependencies = [
|
|||
"pfacts",
|
||||
"pretty_env_logger",
|
||||
"prometheus",
|
||||
"rand 0.8.2",
|
||||
"reqwest 0.10.10",
|
||||
"reqwest 0.11.0",
|
||||
"rand 0.8.1",
|
||||
"reqwest",
|
||||
"ructe",
|
||||
"sdnotify",
|
||||
"serde",
|
||||
|
@ -2815,7 +2631,7 @@ dependencies = [
|
|||
"serde_yaml",
|
||||
"sitemap",
|
||||
"thiserror",
|
||||
"tokio 1.1.0",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
"tracing-subscriber",
|
||||
|
|
15
Cargo.toml
15
Cargo.toml
|
@ -14,43 +14,42 @@ chrono = "0.4"
|
|||
comrak = "0.9"
|
||||
envy = "0.4"
|
||||
glob = "0.3"
|
||||
hyper = "0.14"
|
||||
hyper = "0.13"
|
||||
kankyo = "0.3"
|
||||
lazy_static = "1.4"
|
||||
log = "0.4"
|
||||
mime = "0.3.0"
|
||||
prometheus = { version = "0.11", default-features = false, features = ["process"] }
|
||||
prometheus = { version = "0.10", default-features = false, features = ["process"] }
|
||||
rand = "0"
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
sdnotify = { version = "0.1", default-features = false }
|
||||
serde_dhall = "0.9.0"
|
||||
serde_dhall = "0.8.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_yaml = "0.8"
|
||||
sitemap = "0.4"
|
||||
thiserror = "1"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio = { version = "0.2", features = ["macros"] }
|
||||
tracing = "0.1"
|
||||
tracing-futures = "0.2"
|
||||
tracing-subscriber = { version = "0.2", features = ["fmt"] }
|
||||
warp = "0.3"
|
||||
warp = "0.2"
|
||||
xml-rs = "0.8"
|
||||
url = "2"
|
||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||
|
||||
# workspace dependencies
|
||||
cfcache = { path = "./lib/cfcache" }
|
||||
go_vanity = { path = "./lib/go_vanity" }
|
||||
jsonfeed = { path = "./lib/jsonfeed" }
|
||||
mi = { path = "./lib/mi" }
|
||||
patreon = { path = "./lib/patreon" }
|
||||
|
||||
[build-dependencies]
|
||||
ructe = { version = "0.13", features = ["warp02"] }
|
||||
ructe = { version = "0.12", features = ["warp02"] }
|
||||
|
||||
[dev-dependencies]
|
||||
pfacts = "0"
|
||||
serde_json = "1"
|
||||
eyre = "0.6"
|
||||
reqwest = { version = "0.10", features = ["json"] }
|
||||
pretty_env_logger = "0"
|
||||
|
||||
[workspace]
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
title: New PGP Key Fingerprint
|
||||
date: 2021-01-15
|
||||
---
|
||||
|
||||
# New PGP Key Fingerprint
|
||||
|
||||
This morning I got an encrypted email, and in the process of trying to decrypt
|
||||
it I discovered that I had _lost_ my PGP key. I have no idea how I lost it. As
|
||||
such, I have created a new PGP key and replaced the one on my website with it.
|
||||
I did the replacement in [this
|
||||
commit](https://github.com/Xe/site/commit/66233bcd40155cf71e221edf08851db39dbd421c),
|
||||
which you can see is verified with a subkey of my new key.
|
||||
|
||||
My new PGP key ID is `803C 935A E118 A224`. The key with the ID `799F 9134 8118
|
||||
1111` should not be used anymore. Here are all the subkey fingerprints:
|
||||
|
||||
```
|
||||
Signature key ....: 378E BFC6 3D79 B49D 8C36 448C 803C 935A E118 A224
|
||||
created ....: 2021-01-15 13:04:28
|
||||
Encryption key....: 8C61 7F30 F331 D21B 5517 6478 8C5C 9BC7 0FC2 511E
|
||||
created ....: 2021-01-15 13:04:28
|
||||
Authentication key: 7BF7 E531 ABA3 7F77 FD17 8F72 CE17 781B F55D E945
|
||||
created ....: 2021-01-15 13:06:20
|
||||
General key info..: pub rsa2048/803C935AE118A224 2021-01-15 Christine Dodrill (Yubikey) <me@christine.website>
|
||||
sec> rsa2048/803C935AE118A224 created: 2021-01-15 expires: 2031-01-13
|
||||
card-no: 0006 03646872
|
||||
ssb> rsa2048/8C5C9BC70FC2511E created: 2021-01-15 expires: 2031-01-13
|
||||
card-no: 0006 03646872
|
||||
ssb> rsa2048/CE17781BF55DE945 created: 2021-01-15 expires: 2031-01-13
|
||||
card-no: 0006 03646872
|
||||
```
|
||||
|
||||
I don't really know what the proper way is to go about revoking an old PGP key.
|
||||
It probably doesn't help that I don't use PGP very often. I think this is the
|
||||
first encrypted email I've gotten in a year.
|
||||
|
||||
Let's hope that I don't lose this key as easily!
|
|
@ -1,332 +0,0 @@
|
|||
---
|
||||
title: Encrypted Secrets with NixOS
|
||||
date: 2021-01-20
|
||||
series: nixos
|
||||
tags:
|
||||
- age
|
||||
- ed25519
|
||||
---
|
||||
|
||||
# Encrypted Secrets with NixOS
|
||||
|
||||
One of the best things about NixOS is the fact that it's so easy to do
|
||||
configuration management using it. The Nix store (where all your packages live)
|
||||
has a huge flaw for secret management though: everything in the Nix store is
|
||||
globally readable. This means that anyone logged into or running code on the
|
||||
system could read any secret in the Nix store without any limits. This is
|
||||
sub-optimal if your goal is to keep secret values secret. There have been a few
|
||||
approaches to this over the years, but I want to describe how I'm doing it.
|
||||
Here are my goals and implementation for this setup and how a few other secret
|
||||
management strategies don't quite pan out.
|
||||
|
||||
At a high level I have these goals:
|
||||
|
||||
* It should be trivial to declare new secrets
|
||||
* Secrets should never be globally readable in any useful form
|
||||
* If I restart the machine, I should not need to take manual human action to
|
||||
ensure all of the services come back online
|
||||
* GPG should be avoided at all costs
|
||||
|
||||
As a side goal being able to roll back secret changes would also be nice.
|
||||
|
||||
The two biggest tools that offer a way to help with secret management on NixOS
|
||||
that come to mind are NixOps and Morph.
|
||||
|
||||
[NixOps](https://github.com/NixOS/nixops) is a tool that helps administrators
|
||||
operate NixOS across multiple servers at once. I use NixOps extensively in my
|
||||
own setup. It calls deployment secrets "keys" and they are documented
|
||||
[here](https://hydra.nixos.org/build/115931128/download/1/manual/manual.html#idm140737322649152).
|
||||
At a high level they are declared like this:
|
||||
|
||||
```nix
|
||||
deployment.keys.example = {
|
||||
text = "this is a super sekrit value :)";
|
||||
user = "example";
|
||||
group = "keys";
|
||||
permissions = "0400";
|
||||
};
|
||||
```
|
||||
|
||||
This will create a new secret in `/run/keys` that will contain our super secret
|
||||
value.
|
||||
|
||||
[Wait, isn't `/run` an ephemeral filesystem? What happens when the system
|
||||
reboots?](conversation://Mara/hmm)
|
||||
|
||||
Let's make an example system and find out! So let's say we have that `example`
|
||||
secret from earlier and want to use it in a job. The job definition could look
|
||||
something like this:
|
||||
|
||||
```nix
|
||||
# create a service-specific user
|
||||
users.users.example.isSystemUser = true;
|
||||
|
||||
# without this group the secret can't be read
|
||||
users.users.example.extraGroups = [ "keys" ];
|
||||
|
||||
systemd.services.example = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "example-key.service" ];
|
||||
wants = [ "example-key.service" ];
|
||||
|
||||
serviceConfig.User = "example";
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
script = ''
|
||||
stat /run/keys/example
|
||||
'';
|
||||
};
|
||||
```
|
||||
|
||||
This creates a user called `example` and gives it permission to read deployment
|
||||
keys. It also creates a systemd service called `example.service` and runs
|
||||
[`stat(1)`](https://linux.die.net/man/1/stat) to show the permissions of the
|
||||
service and the key file. It also runs as our `example` user. To avoid systemd
|
||||
thinking our service failed, we're also going to mark it as a
|
||||
[oneshot](https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files#the-service-section).
|
||||
|
||||
Altogether it could look something like
|
||||
[this](https://gist.github.com/Xe/4a71d7741e508d9002be91b62248144a). Let's see
|
||||
what `systemctl` has to report:
|
||||
|
||||
```console
|
||||
$ nixops ssh -d blog-example pa -- systemctl status example
|
||||
● example.service
|
||||
Loaded: loaded (/nix/store/j4a8f6mnaw3v4sz7dqlnz95psh72xglw-unit-example.service/example.service; enabled; vendor preset: enabled)
|
||||
Active: inactive (dead) since Wed 2021-01-20 20:53:54 UTC; 37s ago
|
||||
Process: 2230 ExecStart=/nix/store/1yg89z4dsdp1axacqk07iq5jqv58q169-unit-script-example-start/bin/example-start (code=exited, status=0/SUCCESS)
|
||||
Main PID: 2230 (code=exited, status=0/SUCCESS)
|
||||
IP: 0B in, 0B out
|
||||
CPU: 3ms
|
||||
|
||||
Jan 20 20:53:54 pa example-start[2235]: File: /run/keys/example
|
||||
Jan 20 20:53:54 pa example-start[2235]: Size: 31 Blocks: 8 IO Block: 4096 regular file
|
||||
Jan 20 20:53:54 pa example-start[2235]: Device: 18h/24d Inode: 37428 Links: 1
|
||||
Jan 20 20:53:54 pa example-start[2235]: Access: (0400/-r--------) Uid: ( 998/ example) Gid: ( 96/ keys)
|
||||
Jan 20 20:53:54 pa example-start[2235]: Access: 2021-01-20 20:53:54.010554201 +0000
|
||||
Jan 20 20:53:54 pa example-start[2235]: Modify: 2021-01-20 20:53:54.010554201 +0000
|
||||
Jan 20 20:53:54 pa example-start[2235]: Change: 2021-01-20 20:53:54.398103181 +0000
|
||||
Jan 20 20:53:54 pa example-start[2235]: Birth: -
|
||||
Jan 20 20:53:54 pa systemd[1]: example.service: Succeeded.
|
||||
Jan 20 20:53:54 pa systemd[1]: Finished example.service.
|
||||
```
|
||||
|
||||
So what happens when we reboot? I'll force a reboot in my hypervisor and we'll
|
||||
find out:
|
||||
|
||||
```console
|
||||
$ nixops ssh -d blog-example pa -- systemctl status example
|
||||
● example.service
|
||||
Loaded: loaded (/nix/store/j4a8f6mnaw3v4sz7dqlnz95psh72xglw-unit-example.service/example.service; enabled; vendor preset: enabled)
|
||||
Active: inactive (dead)
|
||||
```
|
||||
|
||||
The service is inactive. Let's see what the status of `example-key.service` is:
|
||||
|
||||
```console
|
||||
$ nixops ssh -d blog-example pa -- systemctl status example-key
|
||||
● example-key.service
|
||||
Loaded: loaded (/nix/store/ikqn64cjq8pspkf3ma1jmx8qzpyrckpb-unit-example-key.service/example-key.service; linked; vendor preset: enabled)
|
||||
Active: activating (start-pre) since Wed 2021-01-20 20:56:05 UTC; 3min 1s ago
|
||||
Cntrl PID: 610 (example-key-pre)
|
||||
IP: 0B in, 0B out
|
||||
IO: 116.0K read, 0B written
|
||||
Tasks: 4 (limit: 2374)
|
||||
Memory: 1.6M
|
||||
CPU: 3ms
|
||||
CGroup: /system.slice/example-key.service
|
||||
├─610 /nix/store/kl6lr3czkbnr6m5crcy8ffwfzbj8a22i-bash-4.4-p23/bin/bash -e /nix/store/awx1zrics3cal8kd9c5d05xzp5ikazlk-unit-script-example-key-pre-start/bin/example-key-pre-start
|
||||
├─619 /nix/store/kl6lr3czkbnr6m5crcy8ffwfzbj8a22i-bash-4.4-p23/bin/bash -e /nix/store/awx1zrics3cal8kd9c5d05xzp5ikazlk-unit-script-example-key-pre-start/bin/example-key-pre-start
|
||||
├─620 /nix/store/kl6lr3czkbnr6m5crcy8ffwfzbj8a22i-bash-4.4-p23/bin/bash -e /nix/store/awx1zrics3cal8kd9c5d05xzp5ikazlk-unit-script-example-key-pre-start/bin/example-key-pre-start
|
||||
└─621 inotifywait -qm --format %f -e create,move /run/keys
|
||||
|
||||
Jan 20 20:56:05 pa systemd[1]: Starting example-key.service...
|
||||
```
|
||||
|
||||
The service is blocked waiting for the keys to exist. We have to populate the
|
||||
keys with `nixops send-keys`:
|
||||
|
||||
```console
|
||||
$ nixops send-keys -d blog-example
|
||||
pa> uploading key ‘example’...
|
||||
```
|
||||
|
||||
Now when we check on `example.service`, we get the following:
|
||||
|
||||
```console
|
||||
$ nixops ssh -d blog-example pa -- systemctl status example
|
||||
● example.service
|
||||
Loaded: loaded (/nix/store/j4a8f6mnaw3v4sz7dqlnz95psh72xglw-unit-example.service/example.service; enabled; vendor preset: enabled)
|
||||
Active: inactive (dead) since Wed 2021-01-20 21:00:24 UTC; 32s ago
|
||||
Process: 954 ExecStart=/nix/store/1yg89z4dsdp1axacqk07iq5jqv58q169-unit-script-example-start/bin/example-start (code=exited, status=0/SUCCESS)
|
||||
Main PID: 954 (code=exited, status=0/SUCCESS)
|
||||
IP: 0B in, 0B out
|
||||
CPU: 3ms
|
||||
|
||||
Jan 20 21:00:24 pa example-start[957]: File: /run/keys/example
|
||||
Jan 20 21:00:24 pa example-start[957]: Size: 31 Blocks: 8 IO Block: 4096 regular file
|
||||
Jan 20 21:00:24 pa example-start[957]: Device: 18h/24d Inode: 27774 Links: 1
|
||||
Jan 20 21:00:24 pa example-start[957]: Access: (0400/-r--------) Uid: ( 998/ example) Gid: ( 96/ keys)
|
||||
Jan 20 21:00:24 pa example-start[957]: Access: 2021-01-20 21:00:24.588494730 +0000
|
||||
Jan 20 21:00:24 pa example-start[957]: Modify: 2021-01-20 21:00:24.588494730 +0000
|
||||
Jan 20 21:00:24 pa example-start[957]: Change: 2021-01-20 21:00:24.606495751 +0000
|
||||
Jan 20 21:00:24 pa example-start[957]: Birth: -
|
||||
Jan 20 21:00:24 pa systemd[1]: example.service: Succeeded.
|
||||
Jan 20 21:00:24 pa systemd[1]: Finished example.service.
|
||||
```
|
||||
|
||||
This means that NixOps secrets require _manual human intervention_ in order to
|
||||
repopulate them on server boot. If your server went offline overnight due to an
|
||||
unexpected issue, your services using those keys could be stuck offline until
|
||||
morning. This is undesirable for a number of reasons. This plus the requirement
|
||||
for the `keys` group (which at time of writing was undocumented) to be added to
|
||||
service user accounts means that while they do work, they are not very
|
||||
ergonomic.
|
||||
|
||||
[You can read secrets from files using something like
|
||||
`deployment.keys.example.text = "${builtins.readFile ./secrets/example.env}"`,
|
||||
but it is kind of a pain to have to do that. It would be better to just
|
||||
reference the secrets by filesystem paths in the first
|
||||
place.](conversation://Mara/hacker)
|
||||
|
||||
On the other hand [Morph](https://github.com/DBCDK/morph) gets this a bit
|
||||
better. It is sadly even less documented than NixOps is, but it offers a similar
|
||||
experience via [deployment
|
||||
secrets](https://github.com/DBCDK/morph/blob/master/examples/secrets.nix). The
|
||||
main differences that Morph brings to the table are taking paths to secrets and
|
||||
allowing you to run an arbitrary command on the secret being uploaded. Secrets
|
||||
are also able to be put anywhere on the disk, meaning that when a host reboots it
|
||||
will come back up with the most recent secrets uploaded to it.
|
||||
|
||||
However, like NixOps, Morph secrets don't have the ability to be rolled back.
|
||||
This means that if you mess up a secret value you better hope you have the old
|
||||
information somewhere. This violates what you'd expect from a NixOS machine.
|
||||
|
||||
So given these examples, I thought it would be interesting to explore what the
|
||||
middle path could look like. I chose to use
|
||||
[age](https://github.com/FiloSottile/age) for encrypting secrets in the Nix
|
||||
store as well as using SSH host keys to ensure that every secret is decryptable
|
||||
at runtime by _that machine only_. If you get your hands on the secret
|
||||
cyphertext, it should be unusable to you.
|
||||
|
||||
One of the harder things here will be keeping a list of all of the server host
|
||||
keys. Recently I added a
|
||||
[hosts.toml](https://github.com/Xe/nixos-configs/blob/master/ops/metadata/hosts.toml)
|
||||
file to my config repo for autoconfiguring my WireGuard overlay network. It was
|
||||
easy enough to add all the SSH host keys for each machine using a command like
|
||||
this to get them:
|
||||
|
||||
[We will cover how this WireGuard overlay works in a future post.](conversation://Mara/hacker)
|
||||
|
||||
```console
|
||||
$ nixops ssh-for-each -d hexagone -- cat /etc/ssh/ssh_host_ed25519_key.pub
|
||||
firgu....> ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB8+mCR+MEsv0XYi7ohvdKLbDecBtb3uKGQOPfIhdj3C root@nixos
|
||||
chrysalis> ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGDA5iXvkKyvAiMEd/5IruwKwoymC8WxH4tLcLWOSYJ1 root@chrysalis
|
||||
lufta....> ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMADhGV0hKt3ZY+uBjgOXX08txBS6MmHZcSL61KAd3df root@lufta
|
||||
keanu....> ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGDZUmuhfjEIROo2hog2c8J53taRuPJLNOtdaT8Nt69W root@nixos
|
||||
```
|
||||
|
||||
age lets you use SSH keys for decryption, so I added these keys to my
|
||||
`hosts.toml` and ended up with something like
|
||||
[this](https://github.com/Xe/nixos-configs/commit/14726e982001e794cd72afa1ece209eed58d3f38#diff-61d1d8dddd71be624c0d718be22072c950ec31c72fded8a25094ea53d94c8185).
|
||||
|
||||
Now we can encrypt secrets on the host machine and safely put them in the Nix
|
||||
store because they will be readable to each target machine with a command like
|
||||
this:
|
||||
|
||||
```shell
|
||||
age -d -i /etc/ssh/ssh_host_ed25519_key -o $dest $src
|
||||
```
|
||||
|
||||
From here it's easy to make a function that we can use for generating new
|
||||
encrypted secrets in the Nix store. First we need to import the host metadata
|
||||
from the toml file:
|
||||
|
||||
```nix
|
||||
let
|
||||
cfg = config.within.secrets;
|
||||
metadata = lib.importTOML ../../ops/metadata/hosts.toml;
|
||||
|
||||
mkSecretOnDisk = name:
|
||||
{ source, ... }:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "${name}-secret";
|
||||
phases = "installPhase";
|
||||
buildInputs = [ pkgs.age ];
|
||||
installPhase =
|
||||
let key = metadata.hosts."${config.networking.hostName}".ssh_pubkey;
|
||||
in ''
|
||||
age -a -r "${key}" -o $out ${source}
|
||||
'';
|
||||
};
|
||||
```
|
||||
|
||||
And then we can generate systemd oneshot jobs with something like this:
|
||||
|
||||
```nix
|
||||
mkService = name:
|
||||
{ source, dest, owner, group, permissions, ... }: {
|
||||
description = "decrypt secret for ${name}";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
script = with pkgs; ''
|
||||
rm -rf ${dest}
|
||||
${age}/bin/age -d -i /etc/ssh/ssh_host_ed25519_key -o ${dest} ${
|
||||
mkSecretOnDisk name { inherit source; }
|
||||
}
|
||||
|
||||
chown ${owner}:${group} ${dest}
|
||||
chmod ${permissions} ${dest}
|
||||
'';
|
||||
};
|
||||
```
|
||||
|
||||
And from there we just need some [boring
|
||||
boilerplate](https://github.com/Xe/nixos-configs/blob/master/common/crypto/default.nix#L8-L38)
|
||||
to define a secret type. Then we declare the secret type and its invocation:
|
||||
|
||||
```nix
|
||||
in {
|
||||
options.within.secrets = mkOption {
|
||||
type = types.attrsOf secret;
|
||||
description = "secret configuration";
|
||||
default = { };
|
||||
};
|
||||
|
||||
config.systemd.services = let
|
||||
units = mapAttrs' (name: info: {
|
||||
name = "${name}-key";
|
||||
value = (mkService name info);
|
||||
}) cfg;
|
||||
in units;
|
||||
}
|
||||
```
|
||||
|
||||
And we have ourself a NixOS module that allows us to:
|
||||
|
||||
* Trivially declare new secrets
|
||||
* Make secrets in the Nix store useless without the key
|
||||
* Make every secret be transparently decrypted on startup
|
||||
* Avoid the use of GPG
|
||||
* Roll back secrets like any other configuration change
|
||||
|
||||
Declaring new secrets works like this (as stolen from [the service definition
|
||||
for the website you are reading right now](https://github.com/Xe/nixos-configs/blob/master/common/services/xesite.nix#L35-L41)):
|
||||
|
||||
```nix
|
||||
within.secrets.example = {
|
||||
source = ./secrets/example.env;
|
||||
dest = "/var/lib/example/.env";
|
||||
owner = "example";
|
||||
group = "nogroup";
|
||||
permissions = "0400";
|
||||
};
|
||||
```
|
||||
|
||||
Barring some kind of cryptographic attack against age, this should allow the
|
||||
secrets to be stored securely. I am working on a way to make this more generic.
|
||||
This overall approach was inspired by [agenix](https://github.com/ryantm/agenix)
|
||||
but made more specific for my needs. I hope this approach will make it easy for
|
||||
me to manage these secrets in the future.
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
title: "Tailscale on NixOS: A New Minecraft Server in Ten Minutes"
|
||||
date: 2021-01-19
|
||||
tags:
|
||||
- link
|
||||
redirect_to: https://tailscale.com/blog/nixos-minecraft/
|
||||
---
|
||||
|
||||
# Tailscale on NixOS: A New Minecraft Server in Ten Minutes
|
||||
|
||||
Check out this post [on the Tailscale
|
||||
blog](https://tailscale.com/blog/nixos-minecraft/)!
|
|
@ -1,20 +0,0 @@
|
|||
[package]
|
||||
name = "cfcache"
|
||||
version = "0.1.0"
|
||||
authors = ["Christine Dodrill <me@christine.website>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
serde_json = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
tracing = "0.1"
|
||||
tracing-futures = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
eyre = "0.6.5"
|
||||
kankyo = "0.3"
|
||||
tokio = { version = "1", features = ["full"] }
|
|
@ -1,15 +0,0 @@
|
|||
use eyre::Result;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
kankyo::init()?;
|
||||
|
||||
let key = std::env::var("CF_TOKEN")?;
|
||||
let zone_id = std::env::var("CF_ZONE_ID")?;
|
||||
|
||||
let cli = cfcache::Client::new(key, zone_id)?;
|
||||
cli.purge(vec!["https://christine.website/.within/health".to_string()])
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
use reqwest::header;
|
||||
use tracing::instrument;
|
||||
|
||||
pub type Result<T = ()> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("json error: {0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
|
||||
#[error("request error: {0}")]
|
||||
Request(#[from] reqwest::Error),
|
||||
|
||||
#[error("invalid header value: {0}")]
|
||||
InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue),
|
||||
}
|
||||
|
||||
pub struct Client {
|
||||
zone_id: String,
|
||||
cli: reqwest::Client,
|
||||
}
|
||||
|
||||
static USER_AGENT: &str = concat!(
|
||||
"xesite ",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
"/",
|
||||
env!("CARGO_PKG_VERSION")
|
||||
);
|
||||
|
||||
impl Client {
|
||||
pub fn new(api_key: String, zone_id: String) -> Result<Self> {
|
||||
let mut headers = header::HeaderMap::new();
|
||||
headers.insert(
|
||||
header::AUTHORIZATION,
|
||||
header::HeaderValue::from_str(&format!("Bearer {}", api_key))?,
|
||||
);
|
||||
|
||||
let cli = reqwest::Client::builder()
|
||||
.user_agent(USER_AGENT)
|
||||
.default_headers(headers)
|
||||
.build()?;
|
||||
|
||||
Ok(Self { zone_id, cli })
|
||||
}
|
||||
|
||||
#[instrument(skip(self), err)]
|
||||
pub async fn purge(&self, urls: Vec<String>) -> Result {
|
||||
#[derive(serde::Serialize)]
|
||||
struct Files {
|
||||
files: Vec<String>,
|
||||
}
|
||||
|
||||
self.cli
|
||||
.post(&format!(
|
||||
"https://api.cloudflare.com/client/v4/zones/{}/purge_cache",
|
||||
self.zone_id
|
||||
))
|
||||
.json(&Files { files: urls })
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -8,8 +8,8 @@ build = "src/build.rs"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
mime = "0.3"
|
||||
warp = "0.3"
|
||||
mime = "0.3.0"
|
||||
warp = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
ructe = { version = "0.13", features = ["warp02"] }
|
||||
ructe = { version = "0.12", features = ["warp02"] }
|
||||
|
|
|
@ -9,7 +9,7 @@ edition = "2018"
|
|||
[dependencies]
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
color-eyre = "0.5"
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
reqwest = { version = "0.10", features = ["json"] }
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
|
@ -17,6 +17,6 @@ tracing = "0.1"
|
|||
tracing-futures = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1", features = ["macros"] }
|
||||
tokio = { version = "0.2", features = ["macros"] }
|
||||
envy = "0.4"
|
||||
pretty_env_logger = "0"
|
||||
|
|
|
@ -34,7 +34,7 @@ impl Client {
|
|||
})
|
||||
}
|
||||
|
||||
#[instrument(skip(self), err)]
|
||||
#[instrument(skip(self))]
|
||||
pub async fn mentioners(&self, url: String) -> Result<Vec<WebMention>> {
|
||||
Ok(self
|
||||
.cli
|
||||
|
@ -46,16 +46,6 @@ impl Client {
|
|||
.json()
|
||||
.await?)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), err)]
|
||||
pub async fn refresh(&self) -> Result<()> {
|
||||
self.cli
|
||||
.post("https://mi.within.website/api/blog/refresh")
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Eq, PartialEq, Clone)]
|
||||
|
|
|
@ -8,7 +8,7 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
reqwest = { version = "0.10", features = ["json"] }
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
|
@ -16,6 +16,6 @@ tracing = "0.1"
|
|||
tracing-futures = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1", features = ["macros"] }
|
||||
tokio = { version = "0.2", features = ["macros"] }
|
||||
envy = "0.4"
|
||||
pretty_env_logger = "0"
|
|
@ -244,34 +244,4 @@ in [ Person::{
|
|||
, gitLink = "https://github.com/nasirhm"
|
||||
, twitter = "https://twitter.com/_nasirhm_"
|
||||
}
|
||||
, Person::{
|
||||
, name = "Eliot Partridge"
|
||||
, tags =
|
||||
[ "python"
|
||||
, "linux"
|
||||
, "typescript"
|
||||
, "javascript"
|
||||
, "docker"
|
||||
, "c#"
|
||||
, "dotnet"
|
||||
, "php"
|
||||
]
|
||||
, gitLink = "https://github.com/BytewaveMLP"
|
||||
}
|
||||
, Person::{
|
||||
, name = "İlteriş Eroğlu"
|
||||
, tags =
|
||||
[ "linux"
|
||||
, "javascript"
|
||||
, "node.js"
|
||||
, "bash"
|
||||
, "nfc"
|
||||
, "python"
|
||||
, "devops"
|
||||
, "networking"
|
||||
, "bgp"
|
||||
]
|
||||
, gitLink = "https://github.com/linuxgemini"
|
||||
, twitter = "https://twitter.com/linuxgemini"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::{fs, path::PathBuf};
|
|||
use tracing::{error, instrument};
|
||||
|
||||
pub mod markdown;
|
||||
pub mod poke;
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct Config {
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
use color_eyre::eyre::Result;
|
||||
use std::{env, time::Duration};
|
||||
use tokio::time::sleep as delay_for;
|
||||
|
||||
#[instrument(err)]
|
||||
pub async fn the_cloud() -> Result<()> {
|
||||
info!("waiting for things to settle");
|
||||
delay_for(Duration::from_secs(10)).await;
|
||||
|
||||
info!("purging cloudflare cache");
|
||||
cloudflare().await?;
|
||||
|
||||
info!("waiting for the cloudflare cache to purge globally");
|
||||
delay_for(Duration::from_secs(45)).await;
|
||||
|
||||
info!("poking mi");
|
||||
mi().await?;
|
||||
|
||||
info!("poking bing");
|
||||
bing().await?;
|
||||
|
||||
info!("poking google");
|
||||
google().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
async fn bing() -> Result<()> {
|
||||
let cli = reqwest::Client::new();
|
||||
cli.get("https://www.bing.com/ping")
|
||||
.query(&[("sitemap", "https://christine.website/sitemap.xml")])
|
||||
.header("User-Agent", crate::APPLICATION_NAME)
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
async fn google() -> Result<()> {
|
||||
let cli = reqwest::Client::new();
|
||||
cli.get("https://www.google.com/ping")
|
||||
.query(&[("sitemap", "https://christine.website/sitemap.xml")])
|
||||
.header("User-Agent", crate::APPLICATION_NAME)
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
async fn cloudflare() -> Result<()> {
|
||||
let cli = cfcache::Client::new(env::var("CF_TOKEN")?, env::var("CF_ZONE_ID")?)?;
|
||||
cli.purge(
|
||||
vec![
|
||||
"https://christine.website/sitemap.xml",
|
||||
"https://christine.website",
|
||||
"https://christine.website/blog",
|
||||
"https://christine.website/blog.atom",
|
||||
"https://christine.website/blog.json",
|
||||
"https://christine.website/blog.rss",
|
||||
"https://christine.website/gallery",
|
||||
"https://christine.website/talks",
|
||||
"https://christine.website/resume",
|
||||
"https://christine.website/signalboost",
|
||||
"https://christine.website/feeds",
|
||||
]
|
||||
.into_iter()
|
||||
.map(|i| i.to_string())
|
||||
.collect(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
async fn mi() -> Result<()> {
|
||||
let cli = mi::Client::new(env::var("MI_TOKEN")?, crate::APPLICATION_NAME.to_string())?;
|
||||
cli.refresh().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -5,11 +5,11 @@ use crate::{
|
|||
use lazy_static::lazy_static;
|
||||
use prometheus::{opts, register_int_counter_vec, IntCounterVec};
|
||||
use std::{convert::Infallible, fmt, sync::Arc};
|
||||
use tracing::instrument;
|
||||
use warp::{
|
||||
http::{Response, StatusCode},
|
||||
Rejection, Reply,
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
lazy_static! {
|
||||
static ref HIT_COUNTER: IntCounterVec =
|
||||
|
@ -86,6 +86,12 @@ impl fmt::Display for PostNotFound {
|
|||
|
||||
impl warp::reject::Reject for PostNotFound {}
|
||||
|
||||
impl From<PostNotFound> for warp::reject::Rejection {
|
||||
fn from(error: PostNotFound) -> Self {
|
||||
warp::reject::custom(error)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
struct SeriesNotFound(String);
|
||||
|
||||
|
@ -97,6 +103,12 @@ impl fmt::Display for SeriesNotFound {
|
|||
|
||||
impl warp::reject::Reject for SeriesNotFound {}
|
||||
|
||||
impl From<SeriesNotFound> for warp::reject::Rejection {
|
||||
fn from(error: SeriesNotFound) -> Self {
|
||||
warp::reject::custom(error)
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref REJECTION_COUNTER: IntCounterVec = register_int_counter_vec!(
|
||||
opts!("rejections", "Number of rejections by kind"),
|
||||
|
|
37
src/main.rs
37
src/main.rs
|
@ -39,6 +39,21 @@ async fn main() -> Result<()> {
|
|||
.await?,
|
||||
);
|
||||
|
||||
match sdnotify::SdNotify::from_env() {
|
||||
Ok(ref mut n) => {
|
||||
n.notify_ready().map_err(|why| {
|
||||
error!("can't signal readiness to systemd: {}", why);
|
||||
why
|
||||
})?;
|
||||
n.set_status(format!("hosting {} posts", state.clone().everything.len()))
|
||||
.map_err(|why| {
|
||||
error!("can't signal status to systemd: {}", why);
|
||||
why
|
||||
})?;
|
||||
}
|
||||
Err(why) => error!("not running under systemd with Type=notify: {}", why),
|
||||
}
|
||||
|
||||
let healthcheck = warp::get().and(warp::path(".within").and(warp::path("health")).map(|| "OK"));
|
||||
|
||||
let base = warp::path!("blog" / ..);
|
||||
|
@ -207,28 +222,6 @@ async fn main() -> Result<()> {
|
|||
.with(warp::log(APPLICATION_NAME))
|
||||
.recover(handlers::rejection);
|
||||
|
||||
match sdnotify::SdNotify::from_env() {
|
||||
Ok(ref mut n) => {
|
||||
// shitty heuristic for detecting if we're running in prod
|
||||
tokio::spawn(async {
|
||||
if let Err(why) = app::poke::the_cloud().await {
|
||||
error!("Unable to poke the cloud: {}", why);
|
||||
}
|
||||
});
|
||||
|
||||
n.notify_ready().map_err(|why| {
|
||||
error!("can't signal readiness to systemd: {}", why);
|
||||
why
|
||||
})?;
|
||||
n.set_status(format!("hosting {} posts", state.clone().everything.len()))
|
||||
.map_err(|why| {
|
||||
error!("can't signal status to systemd: {}", why);
|
||||
why
|
||||
})?;
|
||||
}
|
||||
Err(why) => error!("not running under systemd with Type=notify: {}", why),
|
||||
}
|
||||
|
||||
warp::serve(site)
|
||||
.run((
|
||||
[0, 0, 0, 0],
|
||||
|
|
|
@ -12,7 +12,6 @@ pub struct Data {
|
|||
pub image: Option<String>,
|
||||
pub thumb: Option<String>,
|
||||
pub show: Option<bool>,
|
||||
pub redirect_to: Option<String>,
|
||||
}
|
||||
|
||||
enum State {
|
||||
|
|
123
static/gpg.pub
123
static/gpg.pub
|
@ -1,49 +1,74 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=O4RS
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
JHDVbdWMkg5jUeusy24SURK5WA==
|
||||
=zxPx
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<entry>
|
||||
<id>https://christine.website/@post.link</id>
|
||||
<title>@post.front_matter.title</title>
|
||||
<published>@post.date.to_rfc3339()</published>
|
||||
<updated>@post.date.to_rfc3339()</updated>
|
||||
<link href="https://christine.website/@post.link" rel="alternate"/>
|
||||
</entry>
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@@theprincessxena" />
|
||||
<meta name="twitter:title" content="@post.front_matter.title" />
|
||||
<meta name="twitter:description" content="Posted on @post.date.format("%Y-%m-%d")" />
|
||||
<meta name="twitter:description" content="Posted on @post.date" />
|
||||
|
||||
<!-- Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
|
@ -20,9 +20,7 @@
|
|||
<meta name="description" content="@post.front_matter.title - Christine Dodrill's Blog" />
|
||||
<meta name="author" content="Christine Dodrill">
|
||||
|
||||
@if post.front_matter.redirect_to.is_none() {
|
||||
<link rel="canonical" href="https://christine.website/@post.link">
|
||||
}
|
||||
<link rel="canonical" href="https://christine.website/@post.link">
|
||||
|
||||
<script type="application/ld+json">
|
||||
@{
|
||||
|
@ -31,7 +29,7 @@
|
|||
"headline": "@post.front_matter.title",
|
||||
"image": "https://christine.website/static/img/avatar.png",
|
||||
"url": "https://christine.website/@post.link",
|
||||
"datePublished": "@post.date.format("%Y-%m-%d")",
|
||||
"datePublished": "@post.date",
|
||||
"mainEntityOfPage": @{
|
||||
"@@type": "WebPage",
|
||||
"@@id": "https://christine.website/@post.link"
|
||||
|
@ -47,12 +45,6 @@
|
|||
@}
|
||||
</script>
|
||||
|
||||
@if let Some(to) = post.front_matter.redirect_to.clone() {
|
||||
<script>
|
||||
window.location.replace("@to");
|
||||
</script>
|
||||
}
|
||||
|
||||
@body
|
||||
|
||||
<hr />
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<h3>Email</h3>
|
||||
<p>me@@christine.website</p>
|
||||
|
||||
<p>My GPG fingerprint is <code>803C 935A E118 A224</code>. If you get an email that appears to be from me and the signature does not match that fingerprint, it is not from me. You may download a copy of my public key <a href="/static/gpg.pub">here</a>.</p>
|
||||
<p>My GPG fingerprint is <code>799F 9134 8118 1111</code>. If you get an email that appears to be from me and the signature does not match that fingerprint, it is not from me. You may download a copy of my public key <a href="/static/gpg.pub">here</a>.</p>
|
||||
|
||||
<h3>Social Media</h3>
|
||||
<ul>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@use crate::APPLICATION_NAME as APP;
|
||||
|
||||
@()
|
||||
</div>
|
||||
<hr />
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@@theprincessxena" />
|
||||
<meta name="twitter:title" content="@post.front_matter.title" />
|
||||
<meta name="twitter:description" content="Posted on @post.date.format("%Y-%m-%d")" />
|
||||
<meta name="twitter:description" content="Posted on @post.date" />
|
||||
|
||||
<!-- Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
|
@ -29,7 +29,7 @@
|
|||
"headline": "@post.front_matter.title",
|
||||
"image": "https://christine.website/static/img/avatar.png",
|
||||
"url": "https://christine.website/@post.link",
|
||||
"datePublished": "@post.date.format("%Y-%m-%d")",
|
||||
"datePublished": "@post.date",
|
||||
"mainEntityOfPage": @{
|
||||
"@@type": "WebPage",
|
||||
"@@id": "https://christine.website/@post.link"
|
||||
|
|
|
@ -3,62 +3,8 @@
|
|||
@(title: Option<&str>, styles: Option<&str>)
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
MMMMMMMMMMMMMMMMMMNmmNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmmmd.:mmMM
|
||||
MMMMMMMMMMMMMMMMMNmmmNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmmydmmmmmNMM
|
||||
MMMMMMMMMMMMMMMMNm/:mNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmms /mmmmmMMM
|
||||
MMMMMMMMMMMMMMMNmm:-dmMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmmmmdsdmmmmNMMM
|
||||
MMMMMMMMMMMMMMMmmmmmmmNMMMMMMMMMMMNmmdhhddhhmNNMMMMMMMMMMMMMMMMNmy:hmmmmmmmmMMMM
|
||||
MMMMMMMMMMMMMMNm++mmmmNMMMMMMmdyo/::.........-:/sdNMMMMMMMMMMNmmms`smmmmmmmNMMMM
|
||||
MMMMMMMMMMMMMMmd.-dmmmmMMmhs/-....................-+dNMMMMMMNmmmmmmmmmmmmmmMMMMM
|
||||
MMMMMMMMMMMMMNmmmmmmmmho:-...........................:sNMMNmmmmmmmmmmmmmmmNMNmdd
|
||||
MMMMMMMMMMMMNmd+ydhs/-.................................-sNmmmmmmmmmmmmmmmdhyssss
|
||||
MMMMMMMMMMMNNh+`........................................:dmmmmmmmmmmmmmmmyssssss
|
||||
MMMMNNdhy+:-...........................................+dmmmmmmmmmmmmmmmdsssssss
|
||||
MMMN+-...............................................-smmmmmmmmmmmmmmmmmysyyhdmN
|
||||
MMMMNho:::-.--::-.......................----------..:hmmmmmmmmmmmmmmmmmmmNMMMMMM
|
||||
MMMMMMMMNNNmmdo:......................--------------:ymmmmmmmmmmmmmmmmmmmMMMMMMM
|
||||
MMMMMMMMMMds+........................-----------------+dmmmmmmmmmmmmmmmmmMMMMMMM
|
||||
MMMMMMMMMh+........................--------------------:smmmmmmmmmmmmmmNMMMMMMMM
|
||||
MMMMMMMNy/........................-------------::--------/hmmmmmmmmmmmNMMMMMMNmd
|
||||
MMMMMMMd/........................--------------so----------odmmmmmmmmMMNmdhhysss
|
||||
MMMMMMm/........................--------------+mh-----------:ymmmmdhhyysssssssss
|
||||
MMMMMMo.......................---------------:dmmo------------+dmdysssssssssssss
|
||||
yhdmNh:......................---------------:dmmmm+------------:sssssssssssyhhdm
|
||||
sssssy.......................--------------:hmmmmmmos++:---------/sssyyhdmNMMMMM
|
||||
ssssso......................--------------:hmmmNNNMNdddysso:------:yNNMMMMMMMMMM
|
||||
ysssss.....................--------------/dmNyy/mMMd``d/------------sNMMMMMMMMMM
|
||||
MNmdhy-...................--------------ommmh`o/NM/. smh+-----------:yNMMMMMMMMM
|
||||
MMMMMN+...................------------/hmmss: `-//-.smmmmd+----------:hMMMMMMMMM
|
||||
MMMMMMd:..................----------:smmmmhy+oosyysdmmy+:. `.--------/dMMMMMMMM
|
||||
MMMMMMMh-................---------:smmmmmmmmmmmmmmmh/` `/s:-------sMMMMMMMM
|
||||
MMMMMMMms:...............-------/ymmmmmmmmmmmmmmmd/ :dMMNy/-----+mMMMMMMM
|
||||
MMMMMMmyss/..............------ommmmmmmmmmmmmmmmd. :yMMMMMMNs:---+mMMMMMMM
|
||||
MMMMNdssssso-............----..odmmmmmmmmmmmmmmh:.` .sNMMMMMMMMMd/--sMMMMMMMM
|
||||
MMMmysssssssh/................` -odmmmmmmmmmh+. `omMMMMMMMMMMMMh/+mMMMMMMMM
|
||||
MNdyssssssymMNy-.............. `/sssso+:. `+mMMMMMMMMMMMMMMMdNMMMMMMMMM
|
||||
NhssssssshNMMMMNo:............/.` `+dMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
ysssssssdMMMMMMMMm+-..........+ddy/.` -omMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
ssssssymMMMMMMMMMMMh/.........-oNMMNmy+--` `-+dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
ssssydNMMMMMMMMMMMMMNy:........-hMMMMMMMNmdmMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
sssymMMMMMMMMMMMMMMMMMm+....-..:hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
symNMMMMMMMMMMMMMMMMMMMNo.../-/dMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
dNMMMMMMMMMMMMMMMMMMMMMMh:.:hyNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
la budza pu cusku lu
|
||||
<<.i ko do snura .i ko do kanro
|
||||
.i ko do panpi .i ko do gleki>> li'u
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XLJX94YGBV"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag()@{dataLayer.push(arguments);@}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-XLJX94YGBV');
|
||||
</script>
|
||||
@if title.is_some() {
|
||||
<title>@title.unwrap() - Christine Dodrill</title>
|
||||
} else {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<p>
|
||||
<ul>
|
||||
@for post in posts {
|
||||
<li>@post.date.format("%Y-%m-%d") - <a href="/@post.link">@post.front_matter.title</a></li>
|
||||
<li>@post.date - <a href="/@post.link">@post.front_matter.title</a></li>
|
||||
}
|
||||
</ul>
|
||||
</p>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@@theprincessxena" />
|
||||
<meta name="twitter:title" content="@post.front_matter.title" />
|
||||
<meta name="twitter:description" content="Posted on @post.date.format("%Y-%m-%d")" />
|
||||
<meta name="twitter:description" content="Posted on @post.date" />
|
||||
|
||||
<!-- Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
|
@ -29,7 +29,7 @@
|
|||
"headline": "@post.front_matter.title",
|
||||
"image": "https://christine.website/static/img/avatar.png",
|
||||
"url": "https://christine.website/@post.link",
|
||||
"datePublished": "@post.date.format("%Y-%m-%d")",
|
||||
"datePublished": "@post.date",
|
||||
"mainEntityOfPage": @{
|
||||
"@@type": "WebPage",
|
||||
"@@id": "https://christine.website/@post.link"
|
||||
|
|
Loading…
Reference in New Issue