52 Commits

Author SHA1 Message Date
6607474370 Configure commit signing for Gitea
refs #237
2024-08-09 16:13:58 +02:00
ec9b912e45 Merge pull request 'Configure nginx default vhost, add specific redirects for some domains' (#565) from chore/nginx_redirects into master
Reviewed-on: #565
2024-08-09 12:44:29 +00:00
d53ba42a1d Make kosmos.org the default nginx vhost 2024-08-04 16:51:57 +02:00
a99f7f7574 Add config for accounts .well-known proxyying 2024-08-04 16:51:18 +02:00
1c8ee14bb3 Add HTTP redirects for kosmos.chat and kosmos.cash 2024-08-04 16:49:20 +02:00
cdedf49be3 Merge pull request 'Fix download URLs for Mastodon exports/archives' (#564) from bugfix/mastodon_archive_download_urls into master
Reviewed-on: #564
2024-08-04 14:46:26 +00:00
5e727ec279 Fix download URLs for Mastodon exports/archives
See https://github.com/mastodon/mastodon/issues/24380
2024-08-04 14:55:22 +02:00
9d928298d2 Fix Gitea user/repo avatar URLs in certain situations
I encountered a CORS proxy which somehow ended up with http://_gitea_web
URLs.
2024-07-10 11:36:07 +02:00
1174661b46 Use proxy domain for RS Discourse ACME challenge 2024-07-08 20:31:46 +02:00
2dff7cf850 Merge pull request 'Add new service: nostr.kosmos.org (members-only nostr relay)' (#559) from feature/strfry into master
Reviewed-on: #559
Reviewed-by: Greg <greg@noreply.kosmos.org>
2024-07-05 07:33:40 +00:00
232360efba Remove commented code 2024-07-03 09:23:13 +02:00
8b8e8f3438 Move strfry extras into their own directory 2024-07-03 09:22:50 +02:00
522c213b09 Add Deno lockfile 2024-06-20 18:16:27 +02:00
80eddfbf56 Configure strfry whitelist
Allow akkounts pubkey to publish to our own relay
2024-06-20 15:38:27 +02:00
7e664723a1 Configure akkounts nostr relay URL in production 2024-06-20 15:04:17 +02:00
f5961af7fe Create/deploy strfry VM 2024-06-11 23:17:33 +02:00
d1301dad3e Add, configure, deploy strfry policies 2024-06-11 23:12:22 +02:00
42c46a5645 Deploy strfry reverse proxy 2024-06-11 23:10:24 +02:00
5be9081613 Header name has to be all lowercase in strfry config 2024-06-11 23:09:49 +02:00
1649d03665 Update strfry cookbook 2024-06-11 23:09:48 +02:00
b9a3910364 Update strfry cookbook 2024-06-11 23:09:48 +02:00
9835b85181 Fall back to default port for strfry proxy
When we don't override it elsewhere
2024-06-11 23:09:48 +02:00
dbccd9d2bf Add kosmos_strfry cookbook, configs 2024-06-11 23:09:48 +02:00
1a5f312699 Add strfry cookbook 2024-06-11 23:09:48 +02:00
f843a31e03 Merge pull request 'Improve mail server TLS certificate management' (#556) from chore/mail_server_cert into master
Reviewed-on: #556
Reviewed-by: Greg <greg@noreply.kosmos.org>
2024-06-05 14:49:01 +00:00
ff313525c8 Reload postfix and dovecot on cert renewal
closes #552

Co-authored-by: Greg Karékinian <greg@karekinian.com>
2024-06-05 16:44:18 +02:00
cfb379741e Add imap and smtp subdomains to mail server cert
closes #543

Co-authored-by: Greg Karékinian <greg@karekinian.com>
2024-06-05 15:55:29 +02:00
0c29fad404 Remove superfluous license header
Co-authored-by: Greg Karékinian <greg@karekinian.com>
2024-06-05 15:50:09 +02:00
416935d8b5 Merge pull request 'Upgrade Gitea to 1.22' (#555) from chore/upgrade_gitea into master
Reviewed-on: #555
2024-06-02 21:18:07 +00:00
2b6f81c5d6 Upgrade Gitea to 1.22 2024-06-02 23:17:16 +02:00
18496bb0da Merge pull request 'Configure akkounts for nostr zaps' (#554) from chore/akkounts_config into master
Reviewed-on: #554
2024-06-02 21:05:15 +00:00
d878b4208e Configure akkounts for nostr zaps 2024-06-02 23:03:06 +02:00
d31440d235 Add CORS headers to kosmos.social LNURL paths 2024-06-02 23:02:22 +02:00
6f287f14ef Deploy live branch 2024-06-02 23:01:49 +02:00
b77df3d0db Update email aliases 2024-05-16 14:34:09 +02:00
f7f5a0069d Merge pull request 'Add support for proxy domain validation to tls_cert resource' (#553) from feature/letsencrypt_proxy_validation into master
Reviewed-on: #553
Reviewed-by: Greg <greg@noreply.kosmos.org>
2024-05-08 12:30:29 +00:00
989185f951 Support proxy domain validation for Garage web domains
Also rename the data bag item
2024-04-30 12:23:36 +02:00
4cbda69a6b Add support for proxy domain validation to tls_cert resource 2024-04-26 12:24:17 +02:00
6931fe05d0 Hide Gitea version and load times in footer 2024-04-07 13:16:19 +03:00
b248ef70db Upgrade Gitea to 1.21.10 2024-04-07 13:10:10 +03:00
45159ad4e7 Resolve Mastodon addresses as Lightning Address 2024-03-31 08:27:20 +04:00
612cd0c55e Merge pull request 'Configure LDAP login for Mastodon (merge .social and .org accounts)' (#551) from feature/mastodon_ldap_integration into master
Reviewed-on: #551
Reviewed-by: Greg <greg@noreply.kosmos.org>
2024-03-29 09:51:42 +00:00
83380047bb Configure LDAP integration for Mastodon 2024-03-29 09:28:13 +04:00
8aebb386a4 Configure Mastodon user address domain for akkounts 2024-03-27 20:19:24 +04:00
a8c4f0bd0e Merge pull request 'Only allow ejabberd logins when XMPP service is enabled for user' (#550) from feature/xmpp_service_enabled into master
Reviewed-on: #550
2024-03-27 16:17:04 +00:00
12b4fb37fa Only allow ejabberd logins when XMPP service is enabled 2024-03-27 20:12:33 +04:00
263eb88b72 Add new env var for akkounts 2024-03-14 23:05:05 +01:00
25ee38fe27 Update kredits-ipfs-pinner 2024-03-14 23:04:27 +01:00
e701938442 Merge pull request 'Support letsencrypt proxy validation via CNAMEs' (#548) from feature/letsencrypt_proxy_validation into master
Reviewed-on: #548
Reviewed-by: greg <greg@noreply.kosmos.org>
2024-03-12 14:11:14 +00:00
309bc45791 Merge pull request 'Fix backup script removing image after unsuccessful pivot' (#549) from bugfix/vm_backups into master
Reviewed-on: #549
2024-03-11 15:35:50 +00:00
82a4af05ef Fix backup script removing image after unsuccessful pivot
If pivoting the VM backing storage back to the original image fails
(e.g. VM being down at that time), the script currently still deletes
the hotswap image, which means that all changes since the creation of
the hotswap image are lost.
2024-03-11 16:26:14 +01:00
4a8ab3abe3 Support letsencrypt proxy validation via CNAMEs
Allows to point other domains' `_acme-challenge.example.com` entries at
`example.com.letsencrypt.kosmos.chat` so we can validate from our side
without access to the other domain's DNS records.

Used for 5apps.com XMPP for now. Can be used for others later.

Co-authored-by: Greg Karékinian <greg@karekinian.com>
2024-03-11 16:21:28 +01:00
70 changed files with 1585 additions and 185 deletions

6
.gitmodules vendored
View File

@@ -4,3 +4,9 @@
[submodule "site-cookbooks/openresty"]
path = site-cookbooks/openresty
url = https://github.com/67P/chef-openresty.git
[submodule "site-cookbooks/strfry"]
path = site-cookbooks/strfry
url = git@gitea.kosmos.org:kosmos/strfry-cookbook.git
[submodule "site-cookbooks/deno"]
path = site-cookbooks/deno
url = git@gitea.kosmos.org:kosmos/deno-cookbook.git

View File

@@ -21,6 +21,7 @@ cookbook 'composer', '~> 2.7.0'
cookbook 'fail2ban', '~> 7.0.4'
cookbook 'git', '~> 10.0.0'
cookbook 'golang', '~> 5.3.1'
cookbook 'gpg', '~> 2.0.13'
cookbook 'hostname', '= 0.4.2'
cookbook 'hostsfile', '~> 3.0.1'
cookbook 'java', '~> 4.3.0'

View File

@@ -8,6 +8,7 @@ DEPENDENCIES
firewall (~> 6.2.16)
git (~> 10.0.0)
golang (~> 5.3.1)
gpg (~> 2.0.13)
hostname (= 0.4.2)
hostsfile (~> 3.0.1)
ipfs
@@ -59,6 +60,8 @@ GRAPH
git (10.0.0)
golang (5.3.1)
ark (>= 6.0)
gpg (2.0.13)
yum-epel (>= 0.0.0)
homebrew (5.4.1)
hostname (0.4.2)
hostsfile (>= 0.0.0)

4
clients/strfry-1.json Normal file
View File

@@ -0,0 +1,4 @@
{
"name": "strfry-1",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzDV/RMGMXVDbvoA6PNh8\nQzhtHwYDCFcUSkbrwP6tzh6GpVunGEOdOdhj2V63T2tF1H+lujxQXh5pK7C0D6VZ\niO04ftJlo7/svyxUcwWr+znyN5sFdQRh3cBZiGSBYolizwoqgtPFlbNhmWAzV0Du\n9t8mhz70IK3B+UdwWyHtoK0NNsJGnQ9YzAvcjyDmEO/3sCjAhNnxVpmXftpcSmd9\nMonzFtIDBbRRll4AHZYRbmXCzx63+VmelvdnufnbY82liol0zzBwJaBD1wyNlG0y\ni96p3Kx03bLNlIaYVGbjZeJi+6oo2VDWJ4OloLLAYoHDSipeHT9qWfUdnE6ge4Lm\nywIDAQAB\n-----END PUBLIC KEY-----\n"
}

View File

@@ -0,0 +1,5 @@
config:
ul-indent: false # MD007
line-length: false # MD013
no-duplicate-heading: false # MD024
reference-links-images: false # MD052

View File

@@ -0,0 +1,89 @@
# gpg Cookbook CHANGELOG
This file is used to list changes made in each version of the gpg cookbook.
## 2.0.13 - *2024-05-02*
## 2.0.12 - *2024-05-02*
## 2.0.11 - *2023-09-28*
## 2.0.10 - *2023-09-04*
## 2.0.9 - *2023-07-10*
## 2.0.8 - *2023-05-16*
- Fix markdown formatting in the changelog
- Standardise files with files in sous-chefs/repo-management
## 2.0.7 - *2023-05-16*
- Standardise files with files in sous-chefs/repo-management
## 2.0.6 - *2023-05-03*
- Standardise files with files in sous-chefs/repo-management
## 2.0.5 - *2023-04-01*
- Standardise files with files in sous-chefs/repo-management
## 2.0.4 - *2023-03-02*
- Standardise files with files in sous-chefs/repo-management
## 2.0.3 - *2023-02-14*
- Remove delivery folder
## 2.0.2 - *2021-08-31*
- Standardise files with files in sous-chefs/repo-management
## 2.0.1 - *2021-06-01*
- Standardise files with files in sous-chefs/repo-management
## 2.0.0 - *2021-05-07*
- Update tested platforms
- Set minimum Chef version to 15.3 for unified_mode support
## 1.3.0 - *2020-12-14*
- Added support for SUSE and OpenSUSE
## 1.2.0 (2020-08-26)
- Comment out enforce_idempotency in kitchen.dokken.yml so tests work
- Update/Remove the platforms we test against
- Fix support for pinentry_mode on Ubuntu 16.04
## 1.1.0 (2020-05-14)
- resolved cookstyle error: resources/install.rb:1:36 convention: `Layout/TrailingWhitespace`
- resolved cookstyle error: resources/install.rb:1:37 refactor: `ChefModernize/FoodcriticComments`
## 1.0.1 (2020-01-26)
- Use Github Actions for testing
- Fix Ubuntu platform checks in the `gpg_key` resource
- Use true/false in the resource to simplify the types
## 1.0.0 (2019-01-26)
- Adds two new resources `gpg_install` and `gpg_key`
- Use CircleCI for testing
## 0.3.0 (2018-05-08)
- Sous Chefs will now be maintaining this cookbook. For more information on Sous Chefs see <http://sous-chefs.org/>
- This cookbook now requires Chef 12 or later
- Added a chefignore file
- Added local testing with delivery local mode
- Added Code of conduct, testing, contributing, license, and changelog files
- Added `chef_version`, `source_url`, and `issues_url` to the metadata
- Added ubuntu/debian to the metadata as supported platforms
- Updated the kitchen config to use Vagrant on common platforms
- Resolved all cookstyle / foodcritic warnings

202
cookbooks/gpg/LICENSE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

63
cookbooks/gpg/README.md Normal file
View File

@@ -0,0 +1,63 @@
# GPG cookbook
[![Cookbook Version](https://img.shields.io/cookbook/v/gpg.svg)](https://supermarket.chef.io/cookbooks/gpg)
[![Build Status](https://img.shields.io/circleci/project/github/sous-chefs/gpg/master.svg)](https://circleci.com/gh/sous-chefs/gpg)
[![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors)
[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)
Installs and configures GPG on a system
## Maintainers
This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If youd like to know more please visit [sous-chefs.org](https://sous-chefs.org/) or come chat with us on the Chef Community Slack in [#sous-chefs](https://chefcommunity.slack.com/messages/C2V7B88SF).
## Custom resources
This cookboks uses custom resources to control GPG2.
Install GPG2 and haveged
```ruby
gpg_install
```
Generate a GPG key for a user
```ruby
gpg_key 'foo' do
user 'foo'
passphrase 'this-is-not-secure'
end
```
For further detail please see the documentation for each resource, or the test cookbook for example usage.
- [gpg_install](https://github.com/sous-chefs/gpg/blob/master/documentation/resource/install.md)
- [gpg_key](https://github.com/sous-chefs/gpg/blob/master/documentation/resource/key.md)
- [Test Cookbook](https://github.com/sous-chefs/gpg/blob/master/test/fixtures/cookbooks/test/recipes)
## Contributors
This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false)
### Backers
Thank you to all our backers!
![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40)
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100)

115
cookbooks/gpg/chefignore Normal file
View File

@@ -0,0 +1,115 @@
# Put files/directories that should be ignored in this file when uploading
# to a Chef Infra Server or Supermarket.
# Lines that start with '# ' are comments.
# OS generated files #
######################
.DS_Store
ehthumbs.db
Icon?
nohup.out
Thumbs.db
.envrc
# EDITORS #
###########
.#*
.project
.settings
*_flymake
*_flymake.*
*.bak
*.sw[a-z]
*.tmproj
*~
\#*
REVISION
TAGS*
tmtags
.vscode
.editorconfig
## COMPILED ##
##############
*.class
*.com
*.dll
*.exe
*.o
*.pyc
*.so
*/rdoc/
a.out
mkmf.log
# Testing #
###########
.circleci/*
.codeclimate.yml
.delivery/*
.foodcritic
.kitchen*
.mdlrc
.overcommit.yml
.rspec
.rubocop.yml
.travis.yml
.watchr
.yamllint
azure-pipelines.yml
Dangerfile
examples/*
features/*
Guardfile
kitchen*.yml
mlc_config.json
Procfile
Rakefile
spec/*
test/*
# SCM #
#######
.git
.gitattributes
.gitconfig
.github/*
.gitignore
.gitkeep
.gitmodules
.svn
*/.bzr/*
*/.git
*/.hg/*
*/.svn/*
# Berkshelf #
#############
Berksfile
Berksfile.lock
cookbooks/*
tmp
# Bundler #
###########
vendor/*
Gemfile
Gemfile.lock
# Policyfile #
##############
Policyfile.rb
Policyfile.lock.json
# Documentation #
#############
CODE_OF_CONDUCT*
CONTRIBUTING*
documentation/*
TESTING*
UPGRADING*
# Vagrant #
###########
.vagrant
Vagrantfile

View File

@@ -0,0 +1,43 @@
module Gpg
module Helpers
include Chef::Mixin::ShellOut
def key_exists(new_resource)
gpg_check = gpg_cmd
gpg_check << gpg_opts if new_resource.override_default_keyring
gpg_check << "--list-keys | grep '#{new_resource.name_real}'"
cmd = Mixlib::ShellOut.new(
gpg_check,
user: new_resource.user,
group: new_resource.group
)
cmd.run_command
cmd.exitstatus == 0
end
def gpg_opts(new_resource)
if new_resource.override_default_keyring
"--no-default-keyring --secret-keyring #{new_resource.secring_file} --keyring #{new_resource.pubring_file}"
else
false
end
end
def gpg_cmd
"gpg2 --homedir #{new_resource.home_dir} "
end
def gpg2_packages
packages = %w(haveged)
if platform_family?('suse')
packages.push('gpg2')
else
packages.push('gnupg2')
end
packages
end
end
end

View File

@@ -0,0 +1,43 @@
{
"name": "gpg",
"description": "Installs/Configures gpg",
"long_description": "",
"maintainer": "Sous Chefs",
"maintainer_email": "help@sous-chefs.org",
"license": "Apache-2.0",
"platforms": {
"debian": ">= 0.0.0",
"ubuntu": ">= 0.0.0",
"centos": ">= 0.0.0",
"redhat": ">= 0.0.0",
"oracle": ">= 0.0.0",
"amazon": ">= 0.0.0",
"opensuse": ">= 0.0.0",
"suse": ">= 0.0.0"
},
"dependencies": {
"yum-epel": ">= 0.0.0"
},
"providing": {
},
"recipes": {
},
"version": "2.0.13",
"source_url": "https://github.com/sous-chefs/gpg",
"issues_url": "https://github.com/sous-chefs/gpg/issues",
"privacy": false,
"chef_versions": [
[
">= 15.3"
]
],
"ohai_versions": [
],
"gems": [
],
"eager_load_libraries": true
}

20
cookbooks/gpg/metadata.rb Normal file
View File

@@ -0,0 +1,20 @@
name 'gpg'
maintainer 'Sous Chefs'
maintainer_email 'help@sous-chefs.org'
license 'Apache-2.0'
description 'Installs/Configures gpg'
source_url 'https://github.com/sous-chefs/gpg'
issues_url 'https://github.com/sous-chefs/gpg/issues'
version '2.0.13'
chef_version '>= 15.3'
depends 'yum-epel'
supports 'debian'
supports 'ubuntu'
supports 'centos'
supports 'redhat'
supports 'oracle'
supports 'amazon'
supports 'opensuse'
supports 'suse'

View File

@@ -0,0 +1,18 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"packageRules": [
{
"groupName": "Actions",
"matchUpdateTypes": ["minor", "patch", "pin"],
"automerge": true,
"addLabels": ["Release: Patch", "Skip: Announcements"]
},
{
"groupName": "Actions",
"matchUpdateTypes": ["major"],
"automerge": false,
"addLabels": ["Release: Patch", "Skip: Announcements"]
}
]
}

View File

@@ -0,0 +1,18 @@
unified_mode true
property :name, String, default: ''
action :install do
include_recipe 'yum-epel' if platform_family?('rhel', 'amazon')
package gpg2_packages
service 'haveged' do
supports [:status, :restart]
action :start
end
end
action_class do
include Gpg::Helpers
end

View File

@@ -0,0 +1,166 @@
unified_mode true
property :batch_name, String,
name_property: true,
description: 'Name of the key/batch to generate.'
property :override_default_keyring, [true, false],
default: false,
description: 'Set to true if you want to override the pubring_file and secring_file locations.'
property :pubring_file, String,
description: 'Public keyring file location (override_default_keyring must be set to true or this option will be ignored)'
property :secring_file, String,
description: 'Secret keyring file location (override_default_keyring must be set to true or this option will be ignored)'
property :user, String,
default: 'root',
description: 'User to generate the key for'
property :group, String,
default: lazy { user },
description: 'Group to run the generate command as'
property :key_type, String,
default: '1', equal_to: %w(RSA 1 DSA 17 ),
description: 'Corresponds to GPG option: Key-Type (RSA or DSA)'
property :key_length, String,
default: '2048', equal_to: %w( 2048 4096 ),
description: 'Corresponds to GPG option: Key-Length (2048 or 4096)'
property :name_real, String,
default: lazy { "Chef Generated Default (#{batch_name})" },
description: 'Corresponds to GPG option: Name-Real'
property :name_comment, String,
default: 'generated by Chef',
description: 'Corresponds to GPG option: Name-Comment'
property :name_email, String,
default: lazy { "#{node.name}@example.com" },
description: 'Corresponds to GPG option: Name-Email'
property :expire_date, String,
default: '0',
description: 'Corresponds to GPG option: Expire-Date. Defaults to 0 (no expiry)'
property :home_dir, String,
default: lazy { ::File.expand_path("~#{user}/.gnupg") },
description: 'Location to store the keyring. Defaults to ~/.gnupg'
property :batch_config_file, String,
default: lazy { ::File.join(home_dir, "gpg_batch_config_#{batch_name}") },
description: 'Batch config file name'
property :passphrase, String,
sensitive: true,
description: 'Passphrase for key'
property :key_file, String,
description: 'Keyfile name'
property :key_fingerprint, String,
description: 'Key finger print. Used to identify when deleting keys using the :delete action'
# Only Ubuntu > 16.04 supports the pinetree_mode. And requires it
property :pinentry_mode, [String, FalseClass],
default: platform?('ubuntu') && node['platform_version'].to_f > 16.04 ? 'loopback' : false,
description: 'Pinentry mode. Set to loopback on Ubuntu and False (off) for all other platforms.'
property :batch, [true, false],
default: true,
description: 'Turn batch mode on or off when genrating keys'
action :generate do
unless key_exists(new_resource)
config_dir = ::File.dirname(new_resource.batch_config_file)
directory config_dir do
owner new_resource.user
mode '0700'
recursive true
not_if { ::Dir.exist?(config_dir) }
end
file new_resource.batch_config_file do
content <<~EOS
Key-Type: #{new_resource.key_type}
Key-Length: #{new_resource.key_length}
Name-Real: #{new_resource.name_real}
Name-Comment: #{new_resource.name_comment}
Name-Email: #{new_resource.name_email}
Expire-Date: #{new_resource.expire_date}
EOS
if new_resource.override_default_keyring
content << "%pubring #{new_resource.pubring_file}\n"
content << "%secring #{new_resource.secring_file}\n"
end
content << "Passphrase: #{new_resource.passphrase}" if new_resource.passphrase
content << "%commit\n"
mode '0600'
owner new_resource.user
sensitive true
end
cmd = gpg_cmd
cmd << gpg_opts(new_resource) if new_resource.override_default_keyring
cmd << " --passphrase #{new_resource.passphrase}"
cmd << ' --yes'
cmd << ' --batch' if new_resource.batch
cmd << ' --pinentry-mode loopback' if new_resource.pinentry_mode
cmd << " --gen-key #{new_resource.batch_config_file}"
execute 'gpg2: generate' do
command cmd
live_stream true
user new_resource.user
group new_resource.group
end
end
end
action :import do
execute 'gpg2: import key' do
command "#{gpg_cmd} --import #{new_resource.key_file}"
user new_resource.user
group new_resource.group
not_if { key_exists(new_resource) }
end
end
action :export do
execute 'gpg2: export key' do
command "#{gpg_cmd} --export -a \"#{new_resource.name_real}\" > #{new_resource.key_file}"
user new_resource.user
group new_resource.group
not_if { ::File.exist?(new_resource.key_file) }
end
end
action :delete_public_key do
execute 'gpg2: delete key' do
command "#{gpg_cmd} --batch --yes --delete-key \"#{new_resource.key_fingerprint}\""
user new_resource.user
group new_resource.group
only_if { key_exists(new_resource) }
end
end
action :delete_secret_keys do
execute 'gpg2: delete key' do
command "#{gpg_cmd} --batch --yes --delete-secret-keys \"#{new_resource.key_fingerprint}\""
user new_resource.user
group new_resource.group
only_if { key_exists(new_resource) }
end
end
action_class do
include Gpg::Helpers
end

View File

@@ -1,65 +1,72 @@
{
"id": "akkounts",
"postgresql_username": {
"encrypted_data": "l00Lmdbl5xNq07XU4XmcnRxXsIJaYyMQQ6xI\n",
"iv": "yxvL6hKwlVWmdMzl\n",
"auth_tag": "mMCV9ewJW/0TfVE76WBSZw==\n",
"encrypted_data": "bDlOkEmhvMgyVzPeTNUzYnzRLf3T9cc0cDxt\n",
"iv": "GCCUoqU5pxQ7fGkv\n",
"auth_tag": "Q7mrSHIBluMe3CGVmoR86Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"postgresql_password": {
"encrypted_data": "Q6xWsH6bmI1GfMzme3mBRYrt3XmDwFJ7E4FjYg2Rrw==\n",
"iv": "jcQmuT7Jz3g3XE8d\n",
"auth_tag": "nNMvf9UmP6ikf1BW93QZIw==\n",
"encrypted_data": "wD0HtdsNe/hl4ZaOy8hyr2k4z8TXQrrSja3KNVE47w==\n",
"iv": "tb5yz8WDer0CsGvJ\n",
"auth_tag": "/+K2anuCff/6M7Pu70Smqw==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"sentry_dsn": {
"encrypted_data": "V7cqlH2baN1Ix/ggQFeo9PY6dNKKpnDECaB1cO3XuCfy74oN2ot44nbpCQTA\nUl0+1LQv/qNn/L4gmJkqZfdIXZQqhR+iTc06UJxe3aTKJDw=\n",
"iv": "HJtdKYcApwaxhTXI\n",
"auth_tag": "qyIYK9h6nciJTFXBWOjVOA==\n",
"encrypted_data": "jCz681x0WVixHYZUb62TO+1cgyJMiJ2UMqWcaztx57yDBOIiKW3oSZjuXdhP\n9WCesfXQF/lgzITZno3IKDqzlKjWgbGLC75y8FLguxidCHI=\n",
"iv": "IRNOzN/hLwg1iqax\n",
"auth_tag": "eg9dWnEK04JDb94e4CFa9Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"rails_master_key": {
"encrypted_data": "KAl2Kgq1TXjOm4TNxGwZkPwJeOSNLbLLKiRdb4fTyBFfUhIGGeCS9VvV9kIb\n9sQZ6HLU\n",
"iv": "BBPvDNs6nBXDti5I\n",
"auth_tag": "yjM/0nyUwt+5SSGuLC5qWA==\n",
"encrypted_data": "nUB77VLRp41rluH7hLBwQqPtnh/HsmfLr2VbcIZHWawL3o2TGuY+mj648f9L\n7XsEpgqY\n",
"iv": "fpdbDitqTRHxEKiv\n",
"auth_tag": "I44fn8Ott3L/Y5LYr56U/Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"discourse_connect_secret": {
"encrypted_data": "YHkZGzXeK3nDHaXt3JKmGtCcvMfgvv3yHbvS2C+CLKagOIOe+0+2/CiNuh4U\nxO1Pug==\n",
"iv": "SnUxDpIMQum8ySfN\n",
"auth_tag": "Ny6I+3EoCA1s74JLjjbbyQ==\n",
"encrypted_data": "ENtMn+1XTVFmdEZw7LU6WGoMbSZY654ggm3vPACGfFgqo6r0LhG60c5OTdqv\nZvT5/Q==\n",
"iv": "bL1BmvRhgxFqSM1P\n",
"auth_tag": "sEBZzGWwwYFHn+4B4SsyCA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"lndhub_admin_token": {
"encrypted_data": "dJHxB80Enwkm+2aNuIrp7lILAy2J5tQaChPJCl/BHwMo\n",
"iv": "zHLtD1jTIwvjMt1l\n",
"auth_tag": "IC0adEzsS5YF5YHqabWw2A==\n",
"encrypted_data": "4LPGFoARzI8UYnsJPIk8sax/rAA16pUULEZWn86e2C7L\n",
"iv": "nvjXrOwgfgutwEVw\n",
"auth_tag": "A89RUf1sdcS3FVscNPWYLg==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"btcpay_auth_token": {
"encrypted_data": "YbM0HvgIijluKQBcgfKn6hmWvdbhr0ijR1xKc+BRZCZJsRaJBHTjCbwhH8T9\nVnBESruyjhxphtBetcc=\n",
"iv": "3107v/c2Tonx6/cP\n",
"auth_tag": "jnO9fvoXJW5gbDMRjkdMPA==\n",
"encrypted_data": "ky5iWYF06os0Ek6vIRzWqMTekqJhCOh/Q9DTDIeKhSyk8TnT3O71lCNEt1F5\nXCNq6ux3V6oyHVLWj0o=\n",
"iv": "zk6WnxsY89oNW1F9\n",
"auth_tag": "FAIMXKvQ1T7QKezVSNJbwQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"s3_access_key": {
"encrypted_data": "PFjQKe1us12SNHlReQ4f0qctulPp4d2F3t5t+AGocp87PS/kZx77rtHQtruK\n",
"iv": "BGD8+XchqwPmhhwi\n",
"auth_tag": "XefaZKCVs8hotszALN+kxQ==\n",
"encrypted_data": "KfhfEGwPjOonlz6rpnNTinXFPqX/sIbqQn/aby0UDi/G/7cvEcOiNcCkfuSz\n",
"iv": "Q3rg06v6K9pUDLDY\n",
"auth_tag": "G5ugdlJ896KtYtObKLclJA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"s3_secret_key": {
"encrypted_data": "ziO35x8P1YMaSeenMNQoTWug62b5ZVLFlkMlJEFGnYjHK5qTAn6ir06WnMJC\n0zErzTZsPpcr7KpE/ipWgWHRy7qVbGnd6iVO4t9tf5NjiU2OXfA=\n",
"iv": "S3syCCxh2m+mylLu\n",
"auth_tag": "ZMkyBqXMXr3K3LGqxWvbtA==\n",
"encrypted_data": "N8s1OoDrYXHjqSydQA0kY7dd68Aelq4+/cgmJlYfP92u4YA17V4TR7fsvQZL\nkqjuUSClNYPc0XiCwf/5gxVirE9AO6OmmvSV7lUyu4hcEY6unrU=\n",
"iv": "bXzIVWnX6V0P6PRb\n",
"auth_tag": "1EOjCfsX9P6ETjUsgBvBsA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"nostr_private_key": {
"encrypted_data": "Sf8PEyQ0sqcgxddSlIDxLOVzPjOkTFObsYuTgcxkbEV7igrati4e8QVVUEBD\n1yoLJXelp8jlCr28Ectci29jc53gYSMTLSQsw97uYas2R0dGCqQ=\n",
"iv": "+1CIUyvIUOveLrY4\n",
"auth_tag": "GDqS+IuAIfMBmHIeFXaV7A==\n",
"version": 3,
"cipher": "aes-256-gcm"
}

View File

@@ -1,9 +1,30 @@
{
"id": "dirsrv",
"admin_dn": {
"encrypted_data": "zRtz6Scb9WtUXGyjc0xyvsre0YvqupuaFz+RPApj7DEQTmYyZPVb\n",
"iv": "xfIXMhEBHBWqa4Dz\n",
"auth_tag": "BcA32u1njcnCZ+yrBGSceQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"admin_password": {
"encrypted_data": "i71l5E129mXCcDAyME8sNMUkYUlQMgt7Eh6noyFcLNgbaMo=\n",
"iv": "KNW2B8tpX7ywZwbg\n",
"auth_tag": "GawQ+FSlA5v5YVyryeUxng==\n",
"encrypted_data": "7JpXl3JZDqKWDfYt/wuNbkbob+oRuONhkuAlpqUCCEIn+tY=\n",
"iv": "Lcwc4NDzrfcBaIKQ\n",
"auth_tag": "rrePS3Bhdnwbr2d/o8vMhg==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"service_dn": {
"encrypted_data": "sqRFiZreLeTPQljSfhAuV3DmsPxSC8tzWjCdu+WSSbO67sBQA+xhmGtzBhBD\nDZPGJw+jtAxzuVvPdAjxgAVgxXO6C6WEo87L1tdJewE=\n",
"iv": "GUEGtyRJXrPhWcUs\n",
"auth_tag": "2USsrx//3V7RCyumGCbMkg==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"service_password": {
"encrypted_data": "f2wi8B8SEt6p5G0TF3dZ72j0vMFlvwcP1suxYnshBA==\n",
"iv": "rOnUoxbnkaJtodM+\n",
"auth_tag": "dVLCtBVMjxLfW2D8XjJBdQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
}

View File

@@ -0,0 +1,24 @@
{
"id": "gandi_api",
"key": {
"encrypted_data": "d3/rJMX6B9GuzUt0/mIk/lgQ3qGyQdbNXH6UEm3ZX7DeSl+rbW9FPJCRWg==\n",
"iv": "15YVAYla7PqqVOab\n",
"auth_tag": "xQSq+ld6SDOAER07N4ZkUQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"access_token": {
"encrypted_data": "geQwcNosiJZmqbbMpD/I+a2yueBzpV6C8Rb7vrCD8kR161ZRjvqLe+g/1XpT\n2/65wKYDMTrdto1I030=\n",
"iv": "1sj58eyooOZ8FTYn\n",
"auth_tag": "yBNfgWXaToc06VDLly/HUw==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"domains": {
"encrypted_data": "p5rIQTyCE+0d4HIuA4GKEAFekh7qEC4xe9Rm/kP0DyzY83FO0/4uKIvYoZRB\n",
"iv": "LWlx98NSS1/ngCH1\n",
"auth_tag": "FID+x/LjTZ3cgQV5U2xZLA==\n",
"version": 3,
"cipher": "aes-256-gcm"
}
}

View File

@@ -1,9 +0,0 @@
{
"id": "gandi_api_5apps",
"key": {
"encrypted_data": "+tcD9x5MkNpf2Za5iLM7oTGrmAXxuWFEbyg4xrcWypSkSTjdIncOfD1UoIoS\nGzy1\n",
"iv": "ymls2idI/PdiRZCgsulwrA==\n",
"version": 1,
"cipher": "aes-256-cbc"
}
}

View File

@@ -1,79 +1,93 @@
{
"id": "mastodon",
"paperclip_secret": {
"encrypted_data": "orOIbqFANPCkd4sUTCyyoh4z1o6SBudgH4wKJudTo9dANaHGhWcBUFKrhZi1\nMJTBQx/d0hiDI1P2XN3h+hROCg3JJ8OClUSJH9CfN5GlbWvXh0Nhq7hqy8L3\nLAPL+uigiXI6ObrnKQoD8LeJIB46233uwaCA/7zB6gah0ExJ2DXGH6qq9JSS\nqmTFiy+hT+VHGrUo\n",
"iv": "U4E4NLYLkP0/tTTs\n",
"auth_tag": "WKQ+pDPZp7B791lhC5j3iQ==\n",
"encrypted_data": "VJn4Yd2N7qFV+nWXPjPA8Y2KEXL/gZs2gK5E3DZZc9ogFXV7RtpDtq+NKGJU\ndpR8ohtEZvkyC+iBkMAlnS1sSVKiLdQ1xXvbzkj04mYgjnLvwsZ19uVpBGwR\nt/DON7Bhe5Fw+OyrBQksqNcZQSpB9sMBfgA1IgCpdVGHQ8PmkMbFTaZZYcoF\n7gg3yUw5/0t3vRdL\n",
"iv": "X5atp/KaIurfln/u\n",
"auth_tag": "mVnBoUb5HwhXNYUddJbq8Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"secret_key_base": {
"encrypted_data": "vweClhdY8SqQkK+p0OYUL2B6Fsz5eQDpEYWCtd/eRJfwwYAObbLcMWRC6MwE\neQVMw59bOqYc3RBuv/+WPLtENazA1bYCXBXQr1J6xqjJAz0Mo6KbRyxy5n78\nv8q6RSiao1VVIUXohtFlQgWeV6x5sz34bJxjlHinKvKsgiGXiuVBxYUUfzWQ\nuzrGug09cpZBqfpc\n",
"iv": "Z0/csEBH5/X1+MR+\n",
"auth_tag": "fTvBN6eovi3JVEK0ZX97Nw==\n",
"encrypted_data": "d0sNREFhzQEJhkRzielbCNBJOVAdfThv7zcYTZ1vFZ20i/mzB9GWW2nb+1yn\nNFjAq8wCLpLXn9n3FClE+WOqnAw0jwTlyScRM5lzjKI5SxHKkBQHGyFs2AF8\nqFjEvpiqxhjsc4kNOJGO8DdcyHuulXyaO9fJg8HDnU1ov1vSSuTc0ABKgycY\nMq/Xt10UXnhP8cPw\n",
"iv": "HFT7fdGQ2KRJ2NFy\n",
"auth_tag": "C55JT2msLQCoI+09VKf+Jw==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"otp_secret": {
"encrypted_data": "o1ts1bUgPIzFQXjJ2MpBMLntWkyPxDaJAaU1K3WzmNMXnw5MVlkKKCEFVccd\nPss/MwDuBkbNPhri3ZkH48m9SiayWETVYvw5GZzcVsw4TeMu915O44lfl9tX\nW3XHU+DBps1BVH9535R4X9M1aFW4W4XfwHtS5wcrZqtVhNhS3NSgE4JpN/Dz\nFdcFAOhflnt8fIAN\n",
"iv": "QLsxmIlX1NpxMyHz\n",
"auth_tag": "j1h/PvIoqshTBN5c5IaAsA==\n",
"encrypted_data": "1iH7mUkaUzyn9dfDwMdiJ8X059qWSUO3DqivsOFfI1f44nMnzllaYPu6nh8O\nNLNCOzvsSAonhhaq1X+foOdyPIG2mGhE/juKveDD57/AdZAayHWsbsQlPC4l\nwdShz/ANrq0YZ/zOhpT2sZj1TZavW+S+JlxJFX2kP24D4dUzwG0vNj7522+Q\n9NAApJdUte1ZYF/b\n",
"iv": "00/vs5zTdoC19+pS\n",
"auth_tag": "3cjYqebMshnmWkQ3SdRcCQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"aws_access_key_id": {
"encrypted_data": "YQHUx0GugKu0AtlbGLRGocFEhTGAghWA0DUs1Nxs4Hd3bTIp4lyM\n",
"iv": "54zt2tkQhHtpY7sO\n",
"auth_tag": "ofBJx3QDsjHe66ga3nji8g==\n",
"encrypted_data": "krcfpxOrAkwZR2GP4glTaFg2dw/COw8BO8I+KICqyl4bvpL5NrB9\n",
"iv": "paoDKp6EIU8bjxzF\n",
"auth_tag": "p6Pt/tz5dgGXzW5cO06nBg==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"aws_secret_access_key": {
"encrypted_data": "FAz6xZ+wsCz/KFA+DK6f4V04rxJt+9U/yXUGF9tvce0VqB3scH+T0KDDn1/n\nZ/0G0Tbxt2urRPbPUdI=\n",
"iv": "iapSpeM6lfDMIfNk\n",
"auth_tag": "HlkwUnNeJlOUrZ3ieN5xAQ==\n",
"encrypted_data": "aQySCT7gxeNiMMocq81KtIi+YzrZwMBeTd4LrRSN8iNEikWReJrrfagBwozy\n+Gfdw4bMGzY1dhF1Sl4=\n",
"iv": "R/hvvOvmqq/uoKbx\n",
"auth_tag": "QBJY/3+OprBXO/FSNwv2OQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ldap_bind_dn": {
"encrypted_data": "wDPABdL+DlXz2WWV4XwW20kM4EWPSwc/ajBmbdYMnjFau6c76CIBpbFhrFoj\n3mwDbHz8cgOnLNvozXSV4w6N7URCN/mWWTBHNhd3ppw=\n",
"iv": "8rQ0M4LT1HbCNpq9\n",
"auth_tag": "AuO5R6WCtd75TGJNfgFSCg==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ldap_password": {
"encrypted_data": "y0t8RuptVYiTKmUhaAWsC4c2ZzhQsYeVLeMPiQBn+Q==\n",
"iv": "mixYzDKkPSIDQ/l+\n",
"auth_tag": "DbLlZG7rlgBmyCdJ3nhSYA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"smtp_user_name": {
"encrypted_data": "ivB09/mCRrUaz9X4NFRBiqytjgy/vxN5Nha7gopFq5eSu9v4K9MkaLRqHh1I\nYw==\n",
"iv": "a8WKhRKsUjqBtfmn\n",
"auth_tag": "ib5WJNNaO7bRIspdACmOLw==\n",
"encrypted_data": "Ugc29HUFcirv6jOOlYNs9uvmhfwa2rG41im/MusCx0Vu0AZKcdy0krGi/kCZ\nKg==\n",
"iv": "ZlDK854w+vTNmeJe\n",
"auth_tag": "Nj95g0JMxrT419OLQIX26g==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"smtp_password": {
"encrypted_data": "FxPz2e7fUNqcAu+DDJKlqn8rcSBLmnzigTFf5moZlQ1zz4YVl6pqHisa22Qz\nbfUx9rjU\n",
"iv": "GvRlNDV/b1WawtOP\n",
"auth_tag": "kyRCGfSJQelIwThDT4iQQQ==\n",
"encrypted_data": "D1TGjRfmM1ZeUmzwewlKXfQvvqTSzpzNlK5MKIU8dxbAH175UKn5qiemDEWe\nRYPe1LWT\n",
"iv": "D1OVfD5bMcefM5DP\n",
"auth_tag": "2E/q2gTbdXiLVnOMDeJv9w==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"vapid_private_key": {
"encrypted_data": "DlbEAhd+SkSJoOSuwGhd5bdFlJADnT0w4u0+6m8AJoWJjoSCGAnzzmdHWT/k\nVUDkwiBCkqmEPK0oTvxnl/a8\n",
"iv": "6e0Gay7GVrQad1rI\n",
"auth_tag": "jjVundJ/ITxP/oYgEgzElg==\n",
"encrypted_data": "+87bVrbd/XvWhZH1IYusc4Hla7ZZmylptAyJf48CMG/F3SMEO33OqW2I+UWh\nSkqbxai5+GaMhvZHB8U2Clod\n",
"iv": "HVhNdFQl0TvCcjsa\n",
"auth_tag": "EEQXuQ5keOHXmchhBh+Ixw==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"vapid_public_key": {
"encrypted_data": "+m37w/eWYqdEjsEYQw27FvQC+37ucruOFjZAjo0OgCwA0SoVz4VHX2eSA2AK\njX4CnM91cY4e/WG/ZHKlOMN1PftyQn2bdGaw35nXDanep8z0ROa01JEEi5DE\nUFRKvBmPInTeR6xvemuj7GM=\n",
"iv": "loYbGrAsWGLUZ+BK\n",
"auth_tag": "lAfpEEVQq+n7MLLm/kpmIA==\n",
"encrypted_data": "nBm1lXbn1+Kzol95+QSEjsUI/n7ObhdEqEyfYcVSP/LiLy57KOBQDu6CjSMz\n+PN9yEP4lOjtscqHS29jTC2vi3PSui9XpOFHRxFBnDuyKxczrnID2KlLCNRQ\n228G3VRgFIMAWMYKACgzUk0=\n",
"iv": "xHrVl+4JGkQbfUW3\n",
"auth_tag": "rfFoBMocq17YiDSlOCvWqw==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"s3_key_id": {
"encrypted_data": "4B8OQ0iVCCna4FvC+EuS5prEUWaHRm1+tzXGmFoCQ4WZfhUA1HwT3x651e/R\n",
"iv": "1/zGwcQPQQQCiXIs\n",
"auth_tag": "siK9ph1q3/VVEycy91wkqQ==\n",
"encrypted_data": "pq0+VZhjoxzLuyY34f23wOmuks9Wevt8Wu6muKZAsZMSuU0iJvlRoK/65Qa0\n",
"iv": "QTxO+IfYcpI170ON\n",
"auth_tag": "4ZHva2iBYgDv6DyhMRRXzA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"s3_secret_key": {
"encrypted_data": "BSAc8dE/rQUiVvTGV6Ee/ZUDpq4HZlpoaCZ+lbQAbcnxui4ib0OTLPFwhVJ9\n4OQWahtSzkqxMc6MKWpadLT1a3oTnvnae9b3u40X5b2P3VyZYCM=\n",
"iv": "bqw8GTqLMTs5vD5n\n",
"auth_tag": "+e48L1lYVNda7VE3uLOAHA==\n",
"encrypted_data": "YMZqKtOXDPAME8IWWC+lO8TsxHMzawlbTju9z/Hcb5DnQAOy82QufTN90m73\n/xikUboAdKcA5YGn0mkm+Rt/ygVR6DFirYV3kwi2M3qyGVJifug=\n",
"iv": "9AwabheRFOgC8IKR\n",
"auth_tag": "iU2kkA1q8OsblN5jaZrWGQ==\n",
"version": 3,
"cipher": "aes-256-gcm"
}

View File

@@ -3,6 +3,7 @@
"override_attributes": {
"akkounts": {
"btcpay": {
"public_url": "https://btcpay.kosmos.org",
"store_id": "FNJVVsrVkKaduPDAkRVchdegjwzsNhpceAdonCaXAwBX"
},
"ejabberd": {
@@ -11,6 +12,10 @@
"lndhub": {
"public_url": "https://lndhub.kosmos.org",
"public_key": "024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946"
},
"nostr": {
"public_key": "b3e1b7c1660b7db0ecb93ec55c09e67961171a5c4e9e2602f1b47477ea61c50a",
"relay_url": "wss://nostr.kosmos.org"
}
},
"discourse": {
@@ -33,8 +38,7 @@
"hostmaster@kosmos.org": "mail@kosmos.org",
"postmaster@kosmos.org": "mail@kosmos.org",
"abuse@kosmos.org": "mail@kosmos.org",
"mail@kosmos.org": "foundation@kosmos.org",
"hackerhouse@kosmos.org": "mail@lagrange6.com"
"mail@kosmos.org": "foundation@kosmos.org"
}
},
"garage": {
@@ -73,6 +77,7 @@
},
"kosmos-mastodon": {
"domain": "kosmos.social",
"user_address_domain": "kosmos.social",
"s3_endpoint": "http://localhost:3900",
"s3_region": "garage",
"s3_bucket": "kosmos-social",
@@ -97,6 +102,20 @@
},
"sentry": {
"allowed_ips": "10.1.1.0/24"
},
"strfry": {
"domain": "nostr.kosmos.org",
"real_ip_header": "x-real-ip",
"policy_path": "/opt/strfry/strfry-policy.ts",
"whitelist_pubkeys": [
"b3e1b7c1660b7db0ecb93ec55c09e67961171a5c4e9e2602f1b47477ea61c50a"
],
"info": {
"name": "Kosmos Relay",
"description": "Members-only nostr relay for kosmos.org users",
"pubkey": "1f79058c77a224e5be226c8f024cacdad4d741855d75ed9f11473ba8eb86e1cb",
"contact": "ops@kosmos.org"
}
}
}
}

View File

@@ -54,8 +54,10 @@
"kosmos_liquor-cabinet::nginx",
"kosmos_rsk::nginx_testnet",
"kosmos_rsk::nginx_mainnet",
"kosmos_strfry::nginx",
"kosmos_website",
"kosmos_website::default",
"kosmos_website::redirects",
"kosmos-akkounts::nginx",
"kosmos-akkounts::nginx_api",
"kosmos-bitcoin::nginx_lndhub",

View File

@@ -48,8 +48,10 @@
"kosmos_liquor-cabinet::nginx",
"kosmos_rsk::nginx_testnet",
"kosmos_rsk::nginx_mainnet",
"kosmos_strfry::nginx",
"kosmos_website",
"kosmos_website::default",
"kosmos_website::redirects",
"kosmos-akkounts::nginx",
"kosmos-akkounts::nginx_api",
"kosmos-bitcoin::nginx_lndhub",

View File

@@ -14,6 +14,7 @@
"ipaddress": "192.168.122.161",
"roles": [
"kvm_guest",
"ldap_client",
"garage_gateway",
"mastodon",
"postgresql_client"
@@ -22,6 +23,7 @@
"kosmos-base",
"kosmos-base::default",
"kosmos_kvm::guest",
"kosmos-dirsrv::hostsfile",
"kosmos_garage",
"kosmos_garage::default",
"kosmos_garage::firewall_rpc",
@@ -84,6 +86,7 @@
"run_list": [
"recipe[kosmos-base]",
"role[kvm_guest]",
"role[ldap_client]",
"role[garage_gateway]",
"role[mastodon]"
]

66
nodes/strfry-1.json Normal file
View File

@@ -0,0 +1,66 @@
{
"name": "strfry-1",
"chef_environment": "production",
"normal": {
"knife_zero": {
"host": "10.1.1.164"
}
},
"automatic": {
"fqdn": "strfry-1",
"os": "linux",
"os_version": "5.15.0-1060-kvm",
"hostname": "strfry-1",
"ipaddress": "192.168.122.54",
"roles": [
"base",
"kvm_guest",
"strfry",
"ldap_client"
],
"recipes": [
"kosmos-base",
"kosmos-base::default",
"kosmos_kvm::guest",
"kosmos-dirsrv::hostsfile",
"strfry",
"strfry::default",
"kosmos_strfry::policies",
"kosmos_strfry::firewall",
"apt::default",
"timezone_iii::default",
"timezone_iii::debian",
"ntp::default",
"ntp::apparmor",
"kosmos-base::systemd_emails",
"apt::unattended-upgrades",
"kosmos-base::firewall",
"kosmos-postfix::default",
"postfix::default",
"postfix::_common",
"postfix::_attributes",
"postfix::sasl_auth",
"hostname::default",
"deno::default"
],
"platform": "ubuntu",
"platform_version": "22.04",
"cloud": null,
"chef_packages": {
"chef": {
"version": "18.4.12",
"chef_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/chef-18.4.12/lib",
"chef_effortless": null
},
"ohai": {
"version": "18.1.11",
"ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.1.0/gems/ohai-18.1.11/lib/ohai"
}
}
},
"run_list": [
"role[base]",
"role[kvm_guest]",
"role[strfry]"
]
}

View File

@@ -28,7 +28,9 @@ production_run_list = %w(
kosmos_liquor-cabinet::nginx
kosmos_rsk::nginx_testnet
kosmos_rsk::nginx_mainnet
kosmos_strfry::nginx
kosmos_website::default
kosmos_website::redirects
kosmos-akkounts::nginx
kosmos-akkounts::nginx_api
kosmos-bitcoin::nginx_lndhub

8
roles/strfry.rb Normal file
View File

@@ -0,0 +1,8 @@
name "strfry"
run_list %w(
role[ldap_client]
strfry::default
kosmos_strfry::policies
kosmos_strfry::firewall
)

1
site-cookbooks/deno Submodule

Submodule site-cookbooks/deno added at 617f7959ab

View File

@@ -1,5 +1,5 @@
node.default['akkounts']['repo'] = 'https://gitea.kosmos.org/kosmos/akkounts.git'
node.default['akkounts']['revision'] = 'master'
node.default['akkounts']['revision'] = 'live'
node.default['akkounts']['port'] = 3000
node.default['akkounts']['domain'] = 'accounts.kosmos.org'
node.default['akkounts']['primary_domain'] = 'kosmos.org'
@@ -11,6 +11,7 @@ node.default['akkounts']['smtp']['domain'] = 'kosmos.org'
node.default['akkounts']['smtp']['auth_method'] = 'plain'
node.default['akkounts']['smtp']['enable_starttls'] = 'auto'
node.default['akkounts']['btcpay']['public_url'] = nil
node.default['akkounts']['btcpay']['store_id'] = nil
node.default['akkounts']['ejabberd']['admin_url'] = nil
@@ -20,6 +21,9 @@ node.default['akkounts']['lndhub']['public_url'] = nil
node.default['akkounts']['lndhub']['public_key'] = nil
node.default['akkounts']['lndhub']['postgres_db'] = 'lndhub'
node.default['akkounts']['nostr']['public_key'] = nil
node.default['akkounts']['nostr']['relay_url'] = nil
node.default['akkounts']['s3_enabled'] = true
node.default['akkounts']['s3_endpoint'] = "https://s3.kosmos.org"
node.default['akkounts']['s3_region'] = "garage"

View File

@@ -75,6 +75,7 @@ end
if btcpay_host
env[:btcpay_api_url] = "http://#{btcpay_host}:23001/api/v1"
env[:btcpay_public_url] = node['akkounts']['btcpay']['public_url']
env[:btcpay_store_id] = node['akkounts']['btcpay']['store_id']
env[:btcpay_auth_token] = credentials["btcpay_auth_token"]
end
@@ -148,6 +149,7 @@ end
#
env[:mastodon_public_url] = "https://#{node['kosmos-mastodon']['domain']}"
env[:mastodon_address_domain] = node['kosmos-mastodon']['user_address_domain']
#
# MediaWiki
@@ -155,6 +157,14 @@ env[:mastodon_public_url] = "https://#{node['kosmos-mastodon']['domain']}"
env[:mediawiki_public_url] = node['mediawiki']['url']
#
# Nostr
#
env[:nostr_private_key] = credentials['nostr_private_key']
env[:nostr_public_key] = node['akkounts']['nostr']['public_key']
env[:nostr_relay_url] = node['akkounts']['nostr']['relay_url']
#
# remoteStorage / Liquor Cabinet
#

View File

@@ -2,27 +2,6 @@
# Cookbook Name:: kosmos-base
# Recipe:: letsencrypt
#
# The MIT License (MIT)
#
# Copyright:: 2019, Kosmos Developers
#
# 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.
unless platform?('ubuntu')
raise "This recipe only supports Ubuntu installs"

View File

@@ -3,6 +3,8 @@ provides :tls_cert_for
property :domain, [String, Array], name_property: true
property :auth, [String, NilClass], default: nil
property :deploy_hook, [String, NilClass], default: nil
property :acme_domain, [String, NilClass], default: nil
default_action :create
@@ -17,13 +19,35 @@ action :create do
case new_resource.auth
when "gandi_dns"
gandi_api_data_bag_item = data_bag_item('credentials', 'gandi_api_5apps')
gandi_api_credentials = data_bag_item('credentials', 'gandi_api')
hook_path = "/root/gandi_dns_certbot_hook.sh"
hook_auth_command = "#{hook_path} auth"
hook_cleanup_command = "#{hook_path} cleanup"
if new_resource.acme_domain
hook_auth_command += " #{new_resource.acme_domain}"
hook_cleanup_command += " #{new_resource.acme_domain}"
end
template hook_path do
cookbook "kosmos-base"
variables gandi_api_key: gandi_api_data_bag_item["key"]
mode 0770
variables access_token: gandi_api_credentials["access_token"]
mode 0700
sensitive true
end
if new_resource.deploy_hook
deploy_hook_path = "/etc/letsencrypt/renewal-hooks/#{domains.first}"
file deploy_hook_path do
content new_resource.deploy_hook
mode 0755
owner "root"
group "root"
end
elsif node.run_list.roles.include?("openresty_proxy")
deploy_hook_path = "/etc/letsencrypt/renewal-hooks/post/openresty"
end
# Generate a Let's Encrypt cert (only if no cert has been generated before).
@@ -34,10 +58,10 @@ action :create do
--preferred-challenges dns \
--manual-public-ip-logging-ok \
--agree-tos \
--manual-auth-hook '#{hook_path} auth' \
--manual-cleanup-hook '#{hook_path} cleanup' \
--manual-auth-hook '#{hook_auth_command}' \
--manual-cleanup-hook '#{hook_cleanup_command}' \
--email ops@kosmos.org \
#{node.run_list.roles.include?("openresty_proxy") ? '--deploy-hook /etc/letsencrypt/renewal-hooks/post/openresty' : nil } \
#{"--deploy-hook #{deploy_hook_path}" if defined?(deploy_hook_path)} \
#{domains.map {|d| "-d #{d}" }.join(" ")}
CMD
not_if do

View File

@@ -1,21 +1,16 @@
#!/usr/bin/env bash
#
set -euf -o pipefail
# ************** USAGE **************
#
# Example usage (with this hook file saved in /root/):
# Example usage:
#
# sudo su -
# certbot certonly --manual --preferred-challenges dns --manual-public-ip-logging-ok --agree-tos -d "5apps.com" -d muc.5apps.com -d "xmpp.5apps.com" \
# --manual-auth-hook "/root/letsencrypt_hook.sh auth" --manual-cleanup-hook "/root/letsencrypt_hook.sh cleanup"
#
# This hook requires configuration, continue reading.
#
# ************** CONFIGURATION **************
#
# GANDI_API_KEY: Your Gandi Live API key
# ACCESS_TOKEN: Your Gandi Live API key
#
# PROVIDER_UPDATE_DELAY:
# How many seconds to wait after updating your DNS records. This may be required,
@@ -25,10 +20,16 @@ set -euf -o pipefail
#
# Defaults to 30 seconds.
#
GANDI_API_KEY="<%= @gandi_api_key %>"
# VALIDATION_DOMAIN:
# Domain to create ACME DNS entries on. Use this when redirecting ACME subdomains
# from the original domain to a proxy validation domain that we control.
#
ACCESS_TOKEN="<%= @access_token %>"
PROVIDER_UPDATE_DELAY=10
VALIDATION_DOMAIN="${2:-}"
regex='.*\.(.*\..*)'
if [[ $CERTBOT_DOMAIN =~ $regex ]]
then
DOMAIN="${BASH_REMATCH[1]}"
@@ -36,25 +37,41 @@ else
DOMAIN="${CERTBOT_DOMAIN}"
fi
if [[ -n "$VALIDATION_DOMAIN" ]]
then
if [[ $VALIDATION_DOMAIN =~ $regex ]]
then
ACME_BASE_DOMAIN="${BASH_REMATCH[1]}"
else
echo "Validation domain has to be a subdomain, but it is not: \"${VALIDATION_DOMAIN}\""
exit 1
fi
ACME_DOMAIN="${CERTBOT_DOMAIN}.${VALIDATION_DOMAIN}"
else
ACME_BASE_DOMAIN="${DOMAIN}"
ACME_DOMAIN="_acme-challenge.${CERTBOT_DOMAIN}"
fi
# To be invoked via Certbot's --manual-auth-hook
function auth {
curl -s -D- -H "Content-Type: application/json" \
-H "X-Api-Key: ${GANDI_API_KEY}" \
-d "{\"rrset_name\": \"_acme-challenge.${CERTBOT_DOMAIN}.\",
\"rrset_type\": \"TXT\",
\"rrset_ttl\": 3600,
\"rrset_values\": [\"${CERTBOT_VALIDATION}\"]}" \
"https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records"
curl -s -D- \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d "{\"rrset_name\": \"${ACME_DOMAIN}.\",
\"rrset_type\": \"TXT\",
\"rrset_ttl\": 300,
\"rrset_values\": [\"${CERTBOT_VALIDATION}\"]}" \
"https://api.gandi.net/v5/livedns/domains/${ACME_BASE_DOMAIN}/records"
sleep ${PROVIDER_UPDATE_DELAY}
sleep ${PROVIDER_UPDATE_DELAY}
}
# To be invoked via Certbot's --manual-cleanup-hook
function cleanup {
curl -s -X DELETE -H "Content-Type: application/json" \
-H "X-Api-Key: ${GANDI_API_KEY}" \
https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records/_acme-challenge.${CERTBOT_DOMAIN}./TXT
curl -s -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://api.gandi.net/v5/livedns/domains/${ACME_BASE_DOMAIN}/records/${ACME_DOMAIN}./TXT"
}
HANDLER=$1; shift;

View File

@@ -154,6 +154,11 @@ admin_users = ejabberd_credentials['admins']
hosts.each do |host|
ldap_rootdn = "uid=service,ou=#{host[:name]},cn=applications,dc=kosmos,dc=org"
if host[:name] == "kosmos.org"
ldap_filter = "(&(objectClass=person)(serviceEnabled=xmpp))"
else
ldap_filter = "(objectClass=person)"
end
template "/opt/ejabberd/conf/#{host[:name]}.yml" do
source "vhost.yml.erb"
@@ -167,7 +172,8 @@ hosts.each do |host|
ldap_base: ldap_base,
ldap_server: ldap_domain,
ldap_rootdn: ldap_rootdn,
ldap_encryption_type: ldap_encryption_type
ldap_encryption_type: ldap_encryption_type,
ldap_filter: ldap_filter
notifies :reload, "service[ejabberd]", :delayed
end
end

View File

@@ -33,11 +33,11 @@ file "/etc/letsencrypt/renewal-hooks/post/ejabberd" do
group "root"
end
gandi_api_data_bag_item = data_bag_item('credentials', 'gandi_api_5apps')
gandi_api_credentials = data_bag_item('credentials', 'gandi_api')
template "/root/gandi_dns_certbot_hook.sh" do
variables gandi_api_key: gandi_api_data_bag_item["key"]
mode 0770
variables access_token: gandi_api_credentials["access_token"]
mode 0700
end
# Generate a Let's Encrypt cert (only if no cert has been generated before).
@@ -52,7 +52,7 @@ end
# Generate a Let's Encrypt cert (only if no cert has been generated before).
# The systemd timer will take care of renewing
execute "letsencrypt cert for 5apps xmpp" do
command "certbot certonly --manual --preferred-challenges dns --manual-public-ip-logging-ok --agree-tos --manual-auth-hook \"/root/gandi_dns_certbot_hook.sh auth\" --manual-cleanup-hook \"/root/gandi_dns_certbot_hook.sh cleanup\" --deploy-hook \"/etc/letsencrypt/renewal-hooks/post/ejabberd\" --email ops@5apps.com -d 5apps.com -d muc.5apps.com -d xmpp.5apps.com -d uploads.xmpp.5apps.com -n"
command "certbot certonly --manual --preferred-challenges dns --manual-public-ip-logging-ok --agree-tos --manual-auth-hook \"/root/gandi_dns_certbot_hook.sh auth letsencrypt.kosmos.chat\" --manual-cleanup-hook \"/root/gandi_dns_certbot_hook.sh cleanup letsencrypt.kosmos.chat\" --deploy-hook \"/etc/letsencrypt/renewal-hooks/post/ejabberd\" --email ops@5apps.com -d 5apps.com -d muc.5apps.com -d xmpp.5apps.com -d uploads.xmpp.5apps.com -n"
not_if do
File.exist?("/etc/letsencrypt/live/5apps.com/fullchain.pem")
end

View File

@@ -1,21 +1,16 @@
#!/usr/bin/env bash
#
set -euf -o pipefail
# ************** USAGE **************
#
# Example usage (with this hook file saved in /root/):
# Example usage:
#
# sudo su -
# certbot certonly --manual --preferred-challenges dns --manual-public-ip-logging-ok --agree-tos -d "5apps.com" -d muc.5apps.com -d "xmpp.5apps.com" \
# --manual-auth-hook "/root/letsencrypt_hook.sh auth" --manual-cleanup-hook "/root/letsencrypt_hook.sh cleanup"
#
# This hook requires configuration, continue reading.
#
# ************** CONFIGURATION **************
#
# GANDI_API_KEY: Your Gandi Live API key
# ACCESS_TOKEN: Your Gandi Live API key
#
# PROVIDER_UPDATE_DELAY:
# How many seconds to wait after updating your DNS records. This may be required,
@@ -25,10 +20,16 @@ set -euf -o pipefail
#
# Defaults to 30 seconds.
#
GANDI_API_KEY="<%= @gandi_api_key %>"
PROVIDER_UPDATE_DELAY=30
# VALIDATION_DOMAIN:
# Domain to create ACME DNS entries on. Use this when redirecting ACME subdomains
# from the original domain to a proxy validation domain that we control.
#
ACCESS_TOKEN="<%= @access_token %>"
PROVIDER_UPDATE_DELAY=10
VALIDATION_DOMAIN="${2:-}"
regex='.*\.(.*\..*)'
if [[ $CERTBOT_DOMAIN =~ $regex ]]
then
DOMAIN="${BASH_REMATCH[1]}"
@@ -36,25 +37,41 @@ else
DOMAIN="${CERTBOT_DOMAIN}"
fi
if [[ -n "$VALIDATION_DOMAIN" ]]
then
if [[ $VALIDATION_DOMAIN =~ $regex ]]
then
ACME_BASE_DOMAIN="${BASH_REMATCH[1]}"
else
echo "Validation domain has to be a subdomain, but it is not: \"${VALIDATION_DOMAIN}\""
exit 1
fi
ACME_DOMAIN="${CERTBOT_DOMAIN}.${VALIDATION_DOMAIN}"
else
ACME_BASE_DOMAIN="${DOMAIN}"
ACME_DOMAIN="_acme-challenge.${CERTBOT_DOMAIN}"
fi
# To be invoked via Certbot's --manual-auth-hook
function auth {
curl -s -D- -H "Content-Type: application/json" \
-H "X-Api-Key: ${GANDI_API_KEY}" \
-d "{\"rrset_name\": \"_acme-challenge.${CERTBOT_DOMAIN}.\",
\"rrset_type\": \"TXT\",
\"rrset_ttl\": 3600,
\"rrset_values\": [\"${CERTBOT_VALIDATION}\"]}" \
"https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records"
curl -s -D- \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d "{\"rrset_name\": \"${ACME_DOMAIN}.\",
\"rrset_type\": \"TXT\",
\"rrset_ttl\": 300,
\"rrset_values\": [\"${CERTBOT_VALIDATION}\"]}" \
"https://api.gandi.net/v5/livedns/domains/${ACME_BASE_DOMAIN}/records"
sleep ${PROVIDER_UPDATE_DELAY}
sleep ${PROVIDER_UPDATE_DELAY}
}
# To be invoked via Certbot's --manual-cleanup-hook
function cleanup {
curl -s -X DELETE -H "Content-Type: application/json" \
-H "X-Api-Key: ${GANDI_API_KEY}" \
https://dns.api.gandi.net/api/v5/domains/${DOMAIN}/records/_acme-challenge.${CERTBOT_DOMAIN}./TXT
curl -s -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
"https://api.gandi.net/v5/livedns/domains/${ACME_BASE_DOMAIN}/records/${ACME_DOMAIN}./TXT"
}
HANDLER=$1; shift;

View File

@@ -16,7 +16,7 @@ host_config:
ldap_password: "<%= @host[:ldap_password] %>"
ldap_encrypt: <%= @ldap_encryption_type %>
ldap_base: "ou=<%= @host[:name] %>,<%= @ldap_base %>"
ldap_filter: "(objectClass=person)"
ldap_filter: "<%= @ldap_filter %>"
<% end -%>
append_host_config:

View File

@@ -62,4 +62,4 @@ node.default['kosmos-ipfs']['ipfs']['config'] = {
node.default['kosmos-ipfs']['nginx']['domain'] = "ipfs.kosmos.org"
node.default['kosmos-ipfs']['nginx']['external_api_port'] = 5444
node.default['kosmos-ipfs']['kredits-pinner']['revision'] = "v2.2.0"
node.default['kosmos-ipfs']['kredits-pinner']['revision'] = "v2.3.0"

View File

@@ -44,7 +44,7 @@ end
elasticsearch_service 'elasticsearch'
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
postgresql_credentials = data_bag_item('credentials', 'postgresql')
mastodon_path = node["kosmos-mastodon"]["directory"]
mastodon_user = "mastodon"
@@ -168,7 +168,22 @@ execute "restart mastodon services" do
notifies :restart, "service[mastodon-streaming]", :delayed
end
mastodon_credentials = data_bag_item('credentials', 'mastodon')
credentials = data_bag_item('credentials', 'mastodon')
ldap_config = {
host: "ldap.kosmos.local",
port: 389,
method: "plain",
base: "ou=kosmos.org,cn=users,dc=kosmos,dc=org",
bind_dn: credentials["ldap_bind_dn"],
password: credentials["ldap_password"],
uid: "cn",
mail: "mail",
search_filter: "(&(|(cn=%{email})(mail=%{email}))(serviceEnabled=mastodon))",
uid_conversion_enabled: "true",
uid_conversion_search: "-",
uid_conversion_replace: "_"
}
template "#{mastodon_path}/.env.#{rails_env}" do
source "env.erb"
@@ -178,21 +193,22 @@ template "#{mastodon_path}/.env.#{rails_env}" do
variables redis_url: node["kosmos-mastodon"]["redis_url"],
domain: node["kosmos-mastodon"]["domain"],
alternate_domains: node["kosmos-mastodon"]["alternate_domains"],
paperclip_secret: mastodon_credentials['paperclip_secret'],
secret_key_base: mastodon_credentials['secret_key_base'],
otp_secret: mastodon_credentials['otp_secret'],
smtp_login: mastodon_credentials['smtp_user_name'],
smtp_password: mastodon_credentials['smtp_password'],
paperclip_secret: credentials['paperclip_secret'],
secret_key_base: credentials['secret_key_base'],
otp_secret: credentials['otp_secret'],
ldap: ldap_config,
smtp_login: credentials['smtp_user_name'],
smtp_password: credentials['smtp_password'],
smtp_from_address: "mail@#{node['kosmos-mastodon']['domain']}",
s3_endpoint: node["kosmos-mastodon"]["s3_endpoint"],
s3_region: node["kosmos-mastodon"]["s3_region"],
s3_bucket: node["kosmos-mastodon"]["s3_bucket"],
s3_alias_host: node["kosmos-mastodon"]["s3_alias_host"],
aws_access_key_id: mastodon_credentials['s3_key_id'],
aws_secret_access_key: mastodon_credentials['s3_secret_key'],
vapid_private_key: mastodon_credentials['vapid_private_key'],
vapid_public_key: mastodon_credentials['vapid_public_key'],
db_pass: postgresql_data_bag_item['mastodon_user_password'],
aws_access_key_id: credentials['s3_key_id'],
aws_secret_access_key: credentials['s3_secret_key'],
vapid_private_key: credentials['vapid_private_key'],
vapid_public_key: credentials['vapid_public_key'],
db_pass: postgresql_credentials['mastodon_user_password'],
db_host: "pg.kosmos.local",
default_locale: node["kosmos-mastodon"]["default_locale"],
allowed_private_addresses: node["kosmos-mastodon"]["allowed_private_addresses"],

View File

@@ -28,12 +28,15 @@ template "#{node['openresty']['dir']}/snippets/mastodon.conf" do
owner 'www-data'
mode 0640
variables web_root_dir: web_root_dir,
server_name: server_name
server_name: server_name,
s3_private_url: "#{node["kosmos-mastodon"]["s3_endpoint"]}/#{node["kosmos-mastodon"]["s3_bucket"]}/",
s3_public_url: "https://#{node["kosmos-mastodon"]["s3_alias_host"]}/"
notifies :reload, 'service[openresty]', :delayed
end
tls_cert_for server_name do
auth "gandi_dns"
acme_domain "letsencrypt.kosmos.org"
action :create
end

View File

@@ -29,6 +29,23 @@ SMTP_LOGIN=<%= @smtp_login %>
SMTP_PASSWORD=<%= @smtp_password %>
SMTP_FROM_ADDRESS=<%= @smtp_from_address %>
<% if @ldap %>
# LDAP configuration
LDAP_ENABLED=true
LDAP_HOST=<%= @ldap[:host] %>
LDAP_PORT=<%= @ldap[:port] %>
LDAP_METHOD='<%= @ldap[:method] %>'
LDAP_BASE='<%= @ldap[:base] %>'
LDAP_BIND_DN='<%= @ldap[:bind_dn] %>'
LDAP_PASSWORD='<%= @ldap[:password] %>'
LDAP_UID=<%= @ldap[:uid] %>
LDAP_MAIL=<%= @ldap[:mail] %>
LDAP_SEARCH_FILTER='<%= @ldap[:search_filter] %>'
LDAP_UID_CONVERSION_ENABLED=<%= @ldap[:uid_conversion_enabled] %>
LDAP_UID_CONVERSION_SEARCH=<%= @ldap[:uid_conversion_search] %>
LDAP_UID_CONVERSION_REPLACE=<%= @ldap[:uid_conversion_replace] %>
<% end %>
# Optional asset host for multi-server setups
# CDN_HOST=assets.example.com

View File

@@ -32,6 +32,12 @@ server {
<% if @onion_address %>
add_header Onion-Location https://mastodon.<%= @onion_address %>$request_uri;
<% end %>
location ~ ^/.well-known/(lnurlp|keysend) {
add_header 'Access-Control-Allow-Origin' '*';
proxy_ssl_server_name on;
proxy_pass https://accounts.kosmos.org;
}
}
<% if @onion_address %>

View File

@@ -108,11 +108,13 @@ location @proxy {
proxy_pass http://mastodon_app;
proxy_buffering on;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# https://github.com/mastodon/mastodon/issues/24380
proxy_redirect <%= @s3_private_url %> <%= @s3_public_url %>;
tcp_nodelay on;
}

View File

@@ -7,6 +7,7 @@ domain = node["email"]["domain"]
hostname = node["email"]["hostname"]
root_dir = node["email"]["root_directory"]
ip_addr = node["knife_zero"]["host"]
extra_hostnames = ["smtp.#{domain}", "imap.#{domain}"]
node.override["set_fqdn"] = hostname
include_recipe "hostname"
@@ -23,7 +24,9 @@ directory root_dir do
end
tls_cert_for hostname do
domain ([hostname]+extra_hostnames)
auth "gandi_dns"
deploy_hook "systemctl reload postfix.service && systemctl reload dovecot.service"
action :create
end

View File

@@ -3,6 +3,8 @@
# Recipe:: nginx_web
#
gandi_api_credentials = data_bag_item('credentials', 'gandi_api')
file "#{node['openresty']['dir']}/conf.d/garage.conf" do
content <<-EOF
upstream garage_web {
@@ -40,8 +42,12 @@ end
#
node['garage']['s3_web_domains'].each do |domain_name|
second_level_domain = domain_name.match(/(?:.*\.)?([^.]+\.[^.]+)$/) { $1 }
proxy_validation = !gandi_api_credentials["domains"].include?(second_level_domain)
tls_cert_for domain_name do
auth "gandi_dns"
acme_domain "letsencrypt.kosmos.org" if proxy_validation
action :create
end

View File

@@ -1,9 +1,14 @@
node.default["gitea"]["version"] = "1.21.7"
node.default["gitea"]["checksum"] = "fa88e6404d3d34136bdd50c990a8c390d5e05f4cb2e31641559d14234e022bd6"
node.default["gitea"]["version"] = "1.22.0"
node.default["gitea"]["checksum"] = "a31086f073cb9592d28611394b2de3655db515d961e4fdcf5b549cb40753ef3d"
node.default["gitea"]["working_directory"] = "/var/lib/gitea"
node.default["gitea"]["port"] = 3000
node.default["gitea"]["postgresql_host"] = "localhost:5432"
node.default["gitea"]["domain"] = "gitea.kosmos.org"
node.default["gitea"]["commit_signing"] = {
"name_real" => "Gitea",
"name_comment" => "commit signing",
"name_email" => "git@#{node["gitea"]["domain"]}"
}
node.default["gitea"]["config"] = {
"actions": {

View File

@@ -8,6 +8,7 @@ version '0.2.0'
chef_version '>= 14.0'
depends "firewall"
depends "gpg"
depends "kosmos_openresty"
depends "kosmos_postgresql"
depends "backup"

View File

@@ -77,6 +77,22 @@ if node.chef_environment == "production"
}
end
if node["gitea"]["commit_signing"]
gpg_install
gpg_key "git" do
user "git"
group "git"
name_real node["gitea"]["commit_signing"]["name_real"]
name_comment node["gitea"]["commit_signing"]["name_comment"]
name_email node["gitea"]["commit_signing"]["name_email"]
end
execute "enable git commit signing for all repositories" do
command "su - git -c 'git config --global commit.gpgsign true'"
end
end
config_variables = {
working_directory: working_directory,
git_home_directory: git_home_directory,
@@ -93,6 +109,7 @@ config_variables = {
smtp_user: smtp_credentials["user_name"],
smtp_password: smtp_credentials["password"],
config: node["gitea"]["config"],
commit_signing: node["gitea"]["commit_signing"],
s3_key_id: gitea_data_bag_item["s3_key_id"],
s3_secret_key: gitea_data_bag_item["s3_secret_key"],
s3_bucket: gitea_data_bag_item["s3_bucket"]

View File

@@ -28,6 +28,15 @@ SSL_MODE = disable
[repository]
ROOT = <%= @repository_root_directory %>
<% if @commit_signing %>
[repository.signing]
SIGNING_KEY = default
INITIAL_COMMIT = always
CRUD_ACTIONS = always
MERGES = always
WIKI = never
<% end %>
# [indexer]
# ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
@@ -112,3 +121,7 @@ MINIO_USE_SSL=<%= c["use_ssl"] %>
[actions]
ENABLED = true
<% end %>
[other]
SHOW_FOOTER_VERSION = false
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false

View File

@@ -21,8 +21,13 @@ server {
location ~ ^/(avatars|repo-avatars)/.*$ {
proxy_buffers 1024 8k;
proxy_pass http://_gitea_web;
proxy_http_version 1.1;
expires 30d;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Docker registry
@@ -30,12 +35,22 @@ server {
client_max_body_size 0;
proxy_buffers 1024 8k;
proxy_pass http://_gitea_web;
proxy_http_version 1.1;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_buffers 1024 8k;
proxy_pass http://_gitea_web;
proxy_http_version 1.1;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

View File

@@ -1,9 +1,10 @@
ubuntu_server_cloud_image_release = "20230506"
release = "20240514"
img_filename = "ubuntu-22.04-server-cloudimg-amd64-disk-kvm"
node.default["kosmos_kvm"]["host"]["qemu_base_image"] = {
"url" => "https://cloud-images.ubuntu.com/releases/focal/release-#{ubuntu_server_cloud_image_release}/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img",
"checksum" => "27d2b91fd2b715729d739e2a3155dce70d1aaae4f05c177f338b9d4b60be638c",
"path" => "/var/lib/libvirt/images/base/ubuntu-20.04-server-cloudimg-amd64-disk-kvm-#{ubuntu_server_cloud_image_release}.qcow2"
"url" => "https://cloud-images.ubuntu.com/releases/jammy/release-#{release}/#{img_filename}.img",
"checksum" => "2e7698b3ebd7caead06b08bd3ece241e6ce294a6db01f92ea12bcb56d6972c3f",
"path" => "/var/lib/libvirt/images/base/#{img_filename}-#{release}.qcow2"
}
# A systemd.timer OnCalendar config value

View File

@@ -22,8 +22,5 @@ borg create -v $REPOSITORY::$1_$(date +%F_%H-%M) \
/var/lib/libvirt/images/$1.qcow2 \
/root/backups/vm_meta/$1.xml
echo "Pivoting base image back to original"
virsh blockcommit $1 vda --pivot --base=/var/lib/libvirt/images/$1.qcow2
echo "Removing snapshot image"
rm /var/lib/libvirt/images/$1.hotswap.qcow2
echo "Pivoting base image back to original, and removing the snapshot image"
virsh blockcommit $1 vda --pivot --base=/var/lib/libvirt/images/$1.qcow2 && rm /var/lib/libvirt/images/$1.hotswap.qcow2

View File

@@ -0,0 +1,20 @@
Copyright (c) 2024 Kosmos Developers
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.

View File

@@ -0,0 +1,4 @@
kosmos_strfry
=============
Installs/configures a strfry relay and its reverse proxy config

View File

@@ -0,0 +1,2 @@
node.default["strfry"]["ldap_search_dn"] = "ou=kosmos.org,cn=users,dc=kosmos,dc=org"
node.default["strfry"]["extras_dir"] = "/opt/strfry"

View File

@@ -0,0 +1,10 @@
name 'kosmos_strfry'
maintainer 'Kosmos'
maintainer_email 'mail@kosmos.org'
license 'MIT'
description 'strfry wrapper cookbook'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
depends 'kosmos_openresty'
depends 'deno'

View File

@@ -0,0 +1,13 @@
#
# Cookbook Name:: kosmos_strfry
# Recipe:: firewall
#
include_recipe "kosmos-base::firewall"
firewall_rule "strfry" do
port node["strfry"]["port"]
source "10.1.1.0/24"
protocol :tcp
command :allow
end

View File

@@ -0,0 +1,29 @@
#
# Cookbook Name:: kosmos_strfry
# Recipe:: nginx
#
domain = node["strfry"]["domain"]
upstream_hosts = []
search(:node, 'role:strfry').each do |node|
upstream_hosts << node['knife_zero']['host']
end
if upstream_hosts.empty?
Chef::Log.warn("No node found with 'strfry' role. Not configuring nginx site.")
return
end
tls_cert_for domain do
auth "gandi_dns"
action :create
end
openresty_site domain do
template "nginx_conf_strfry.erb"
variables domain: domain,
upstream_port: node['strfry']['port'],
upstream_hosts: upstream_hosts,
ssl_cert: "/etc/letsencrypt/live/#{domain}/fullchain.pem",
ssl_key: "/etc/letsencrypt/live/#{domain}/privkey.pem"
end

View File

@@ -0,0 +1,83 @@
#
# Cookbook Name:: kosmos_strfry
# Recipe:: policies
#
include_recipe "deno"
#
# config
#
ldap_credentials = Chef::EncryptedDataBagItem.load('credentials', 'dirsrv')
extras_dir = node["strfry"]["extras_dir"]
directory extras_dir do
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode "0755"
end
env = {
ldap_url: 'ldap://ldap.kosmos.local:389', # requires "ldap_client" role
ldap_bind_dn: ldap_credentials["service_dn"],
ldap_password: ldap_credentials["service_password"],
ldap_search_dn: node["strfry"]["ldap_search_dn"],
whitelist_pubkeys: node["strfry"]["whitelist_pubkeys"].join(",")
}
template "#{extras_dir}/.env" do
source 'env.erb'
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode 0600
sensitive true
variables config: env
notifies :restart, "service[strfry]", :delayed
end
#
# strfry deno scripts
#
base_url = "https://gitea.kosmos.org/kosmos/akkounts/raw/branch/live/extras/strfry"
remote_file "#{extras_dir}/deno.json" do
source "#{base_url}/deno.json"
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode "0644"
notifies :restart, "service[strfry]", :delayed
end
remote_file "#{extras_dir}/deno.lock" do
source "#{base_url}/deno.lock"
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode "0644"
notifies :restart, "service[strfry]", :delayed
end
remote_file "#{extras_dir}/strfry-policy.ts" do
source "#{base_url}/strfry-policy.ts"
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode "0755"
notifies :restart, "service[strfry]", :delayed
end
remote_file "#{extras_dir}/ldap-policy.ts" do
source "#{base_url}/ldap-policy.ts"
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode "0644"
notifies :restart, "service[strfry]", :delayed
end
remote_file "#{extras_dir}/strfry-sync.ts" do
source "#{base_url}/strfry-sync.ts"
owner node["strfry"]["user"]
group node["strfry"]["group"]
mode "0644"
end

View File

@@ -0,0 +1,11 @@
<% @config.each do |key, value| %>
<% if value.is_a?(Hash) %>
<% value.each do |k, v| %>
<%= "#{key.upcase}_#{k.upcase}" %>=<%= v.to_s %>
<% end %>
<% else %>
<% if value %>
<%= key.upcase %>=<%= value.to_s %>
<% end %>
<% end %>
<% end %>

View File

@@ -0,0 +1,25 @@
upstream _strfry {
<% @upstream_hosts.each do |host| %>
server <%= host %>:<%= @upstream_port || "7777" %>;
<% end %>
}
server {
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
server_name <%= @domain %>;
access_log "/var/log/nginx/<%= @domain %>.access.log";
error_log "/var/log/nginx/<%= @domain %>.error.log";
ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://_strfry;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

View File

@@ -1,3 +1,4 @@
node.default["kosmos_website"]["domain"] = "kosmos.org"
node.default["kosmos_website"]["repo"] = "https://gitea.kosmos.org/kosmos/website.git"
node.default["kosmos_website"]["revision"] = "chore/content"
node.default["kosmos_website"]["domain"] = "kosmos.org"
node.default["kosmos_website"]["repo"] = "https://gitea.kosmos.org/kosmos/website.git"
node.default["kosmos_website"]["revision"] = "chore/content"
node.default["kosmos_website"]["accounts_url"] = "https://accounts.kosmos.org"

View File

@@ -23,6 +23,7 @@ end
openresty_site domain do
template "nginx_conf_website.erb"
variables domain: domain,
accounts_url: node.default["kosmos_website"]["accounts_url"],
ssl_cert: "/etc/letsencrypt/live/#{domain}/fullchain.pem",
ssl_key: "/etc/letsencrypt/live/#{domain}/privkey.pem"
end

View File

@@ -0,0 +1,35 @@
#
# Cookbook:: kosmos_website
# Recipe:: redirects
#
redirects = [
{
domain: "kosmos.chat",
target: "https://kosmos.org",
http_status: 307
},
{
domain: "kosmos.cash",
acme_domain: "letsencrypt.kosmos.org",
target: "https://kosmos.org",
http_status: 307
}
]
redirects.each do |redirect|
tls_cert_for redirect[:domain] do
auth "gandi_dns"
acme_domain redirect[:acme_domain] unless redirect[:acme_domain].nil?
action :create
end
openresty_site redirect[:domain] do
template "nginx_conf_redirect.erb"
variables domain: redirect[:domain],
target: redirect[:target],
http_status: redirect[:http_status],
ssl_cert: "/etc/letsencrypt/live/#{redirect[:domain]}/fullchain.pem",
ssl_key: "/etc/letsencrypt/live/#{redirect[:domain]}/privkey.pem"
end
end

View File

@@ -0,0 +1,20 @@
# Generated by Chef
server {
server_name <%= @domain %>;
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
listen [::]:443 ssl http2;
access_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.access.log;
error_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.error.log warn;
gzip_static on;
gzip_comp_level 5;
ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>;
location / {
return <%= @http_status || 301 %> <%= @target %>;
}
}

View File

@@ -0,0 +1,18 @@
# Generated by Chef
server {
server_name <%= @domain %>;
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
listen [::]:443 ssl http2;
root /var/www/<%= @domain %>/public;
access_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.access.log;
error_log <%= node[:openresty][:log_dir] %>/<%= @domain %>.error.log warn;
gzip_static on;
gzip_comp_level 5;
ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>;
}

View File

@@ -1,9 +1,18 @@
# Generated by Chef
server {
server_name _;
listen 80 default_server;
location / {
return 301 https://<%= @domain %>;
}
}
server {
server_name <%= @domain %>;
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2;
listen [::]:443 ssl http2;
listen <%= "#{node['openresty']['listen_ip']}:" if node['openresty']['listen_ip'] %>443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
root /var/www/<%= @domain %>/public;
@@ -18,8 +27,10 @@ server {
ssl_certificate <%= @ssl_cert %>;
ssl_certificate_key <%= @ssl_key %>;
<% if @accounts_url %>
location ~ ^/.well-known/(webfinger|nostr|lnurlp|keysend) {
proxy_ssl_server_name on;
proxy_pass https://accounts.kosmos.org;
}
<% end %>
}

View File

@@ -18,6 +18,7 @@ end
tls_cert_for domain do
auth "gandi_dns"
acme_domain "letsencrypt.kosmos.org"
action :create
end

View File

@@ -24,10 +24,10 @@ file "/etc/letsencrypt/renewal-hooks/post/nginx" do
group "root"
end
gandi_api_data_bag_item = data_bag_item('credentials', 'gandi_api_5apps')
gandi_api_credentials = data_bag_item('credentials', 'gandi_api')
template "/root/gandi_dns_certbot_hook.sh" do
variables gandi_api_key: gandi_api_data_bag_item["key"]
variables gandi_api_key: gandi_api_credentials["key"]
mode 0770
end

1
site-cookbooks/strfry Submodule

Submodule site-cookbooks/strfry added at a4756377b4