first commit

This commit is contained in:
Tyler 2025-05-26 23:02:42 -04:00
commit 084e9ab432
14 changed files with 511 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea/
*.iml

9
ansible.cfg Normal file
View File

@ -0,0 +1,9 @@
[defaults]
# Use this private key for all SSH connections
private_key_file = ~/.ssh/id_rsa
# Set the default inventory file
inventory = ./inventory.yaml
# Set the default remote user for SSH
remote_user = root

3
inventory.yaml Normal file
View File

@ -0,0 +1,3 @@
seaweed:
hosts:

5
playbook.yaml Normal file
View File

@ -0,0 +1,5 @@
- name: Install SeaweedFS
hosts: seaweed
become: yes
roles:
- seaweed

View File

@ -0,0 +1,60 @@
seaweed_config_dir: /etc/seaweedfs
seaweed_cert_dir: "{{ seaweed_config_dir }}/certs"
seaweed_data_dir: /var/lib/seaweedfs
seaweed_log_dir: /var/log/seaweedfs
seaweed_user: seaweed
seaweed_group: seaweed
download_dir: "/tmp"
seaweed_variant: full # set to large_disk if using large disk variant
seaweed_binary_path: /usr/local/sbin/weed
# Security (Certificates)
seaweed_ca_key: "{{ seaweed_cert_dir }}/ca.key"
seaweed_ca_cert: "{{ seaweed_cert_dir }}/ca.crt"
# SeaweedFS Master
seaweed_master_bind: 0.0.0.0
seaweed_master_host: 127.0.0.1
seaweed_master_port: 9333
# SeaweedFS Volume
seaweed_volume_port: 8080
seaweed_volume_max: 50
# SeaweedFS Filer
seaweed_filer_port: 8888
# SeaweedFS S3
seaweed_s3_port: 8333
seaweed_s3_anonymous: false
seaweed_cert_domains:
- master01
- volume01
- filer01
- client01
seaweedfs_s3_config:
identities:
- name: admin
credentials:
- accessKey: "{{ s3_access_key }}"
secretKey: "{{ s3_secret_key }}"
actions:
- Admin
- Read
- List
- Tagging
- Write
# identities:
# - name: default
# credentials:
# - accessKey: "example"
# secretKey: "example"
# actions:
# - Admin
# - Read
# - List
# - Tagging
# - Write

View File

@ -0,0 +1,37 @@
- name: Ensure certs directory exists
file:
path: "{{ seaweed_config_dir }}/certs"
state: directory
mode: '0700'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
# Use OpenSSL here because the crypto library isn't working properly
- name: Generate CA private key as seaweedfs user
command: openssl genrsa -out {{ seaweed_ca_key }} 4096
args:
creates: "{{ seaweed_ca_key }}"
- name: Generate self-signed CA certificate as seaweedfs user
command: >
openssl req -x509 -new -nodes -key {{ seaweed_ca_key }}
-sha256 -days 3650 -out {{ seaweed_ca_cert }}
-subj "/CN=SeaweedFS CA"
args:
creates: "{{ seaweed_ca_cert }}"
- name: Change ownership of CA files
file:
path: "{{ item }}"
owner: "{{ seaweed_user }}"
group: "{{ seaweed_user }}"
mode: '0644'
loop:
- "{{ seaweed_ca_key }}"
- "{{ seaweed_ca_cert }}"
- name: Generate server private keys and certificates for domains
include_tasks: generate_cert.yaml
loop: "{{ seaweed_cert_domains }}"
loop_control:
loop_var: domain

View File

@ -0,0 +1,28 @@
- name: Determine SeaweedFS asset name based on architecture and disk flag
set_fact:
seaweedfs_asset_name: "{{ asset_name_matrix[ansible_architecture][seaweed_variant] }}"
- name: Ensure download directory exists
file:
path: "{{ download_dir }}"
state: directory
mode: '0755'
- name: Download SeaweedFS latest release artifact
get_url:
url: "https://github.com/seaweedfs/seaweedfs/releases/latest/download/{{ seaweedfs_asset_name }}"
dest: "{{ download_dir }}/{{ seaweedfs_asset_name }}"
mode: '0644'
- name: Extract SeaweedFS archive
unarchive:
src: "{{ download_dir }}/{{ seaweedfs_asset_name }}"
dest: "{{ download_dir }}"
remote_src: yes
- name: Move 'weed' binary to /usr/local/bin
copy:
src: "{{ download_dir }}/weed"
dest: "{{ seaweed_binary_path }}"
mode: '0755'
remote_src: yes

View File

@ -0,0 +1,41 @@
- name: Generate private key for {{ domain }}
command: >
openssl genrsa -out {{ seaweed_cert_dir }}/{{ domain }}.key 2048
args:
creates: "{{ seaweed_cert_dir }}/{{ domain }}.key"
register: gen_key_result
- name: Generate CSR for {{ domain }}
command: >
openssl req -new -key {{ seaweed_cert_dir }}/{{ domain }}.key
-out {{ seaweed_cert_dir }}/{{ domain }}.csr
-subj "/CN={{ domain }}"
args:
creates: "{{ seaweed_cert_dir }}/{{ domain }}.csr"
register: gen_csr_result
- name: Generate certificate signed by CA for {{ domain }}
command: >
openssl x509 -req
-in {{ seaweed_cert_dir }}/{{ domain }}.csr
-CA {{ seaweed_ca_cert }}
-CAkey {{ seaweed_ca_key }}
-CAcreateserial
-out {{ seaweed_cert_dir }}/{{ domain }}.crt
-days 3650
-sha256
args:
creates: "{{ seaweed_cert_dir }}/{{ domain }}.crt"
register: gen_crt_result
- name: Set certificate permissions
file:
path: "{{ item }}"
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
mode: '0644'
recurse: true
loop:
- "{{ seaweed_cert_dir }}/{{ domain }}.crt"
- "{{ seaweed_cert_dir }}/{{ domain }}.csr"
- "{{ seaweed_cert_dir }}/{{ domain }}.key"

View File

@ -0,0 +1,115 @@
- name: Download and Install SeaweedFS
include_tasks: download.yaml
- name: Create system user for SeaweedFS
user:
name: "{{ seaweed_user }}"
shell: /usr/sbin/nologin
system: yes
create_home: no
- name: Create SeaweedFS configuration directory
file:
path: "{{ seaweed_config_dir }}"
state: directory
mode: '0755'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
- name: Create SeaweedFS data directory
file:
path: "{{ seaweed_data_dir }}"
state: directory
mode: '0755'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
- name: Create SeaweedFS log directory
file:
path: "{{ seaweed_log_dir }}"
state: directory
mode: '0755'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
- name: Create SeaweedFS data directories
file:
path: "{{ seaweed_data_dir }}/{{ item.name }}"
state: directory
mode: '0755'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
loop: "{{ seaweed_services }}"
- name: Create certificates
include_tasks: certificates.yaml
- name: Generate seaweed JWT signing secrets
set_fact:
seaweed_jwt_signing: "{{ lookup('password', '/dev/null length=64 chars=ascii_letters,digits') }}"
seaweed_jwt_filer_signing: "{{ lookup('password', '/dev/null length=64 chars=ascii_letters,digits') }}"
- name: Configure security configuration
template:
src: security.toml.j2
dest: "{{ seaweed_config_dir }}/security.toml"
mode: '0644'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
vars:
seaweed_master_cert: "{{ seaweed_cert_dir }}/master01.crt"
seaweed_master_key: "{{ seaweed_cert_dir }}/master01.key"
seaweed_volume_cert: "{{ seaweed_cert_dir }}/volume01.crt"
seaweed_volume_key: "{{ seaweed_cert_dir }}/volume01.key"
seaweed_filer_cert: "{{ seaweed_cert_dir }}/filer01.crt"
seaweed_filer_key: "{{ seaweed_cert_dir }}/filer01.key"
seaweed_client_cert: "{{ seaweed_cert_dir }}/client01.crt"
seaweed_client_key: "{{ seaweed_cert_dir }}/client01.key"
- name: Configure filer
template:
src: filer.toml.j2
dest: "{{ seaweed_config_dir }}/filer.toml"
mode: '0644'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
- name: Generate S3 access key
set_fact:
s3_access_key: "{{ lookup('password', '/dev/null length=20 chars=ascii_letters,digits') }}"
- name: Generate S3 secret key
set_fact:
s3_secret_key: "{{ lookup('password', '/dev/null length=40 chars=ascii_letters,digits') }}"
- name: Configure s3
template:
src: s3.json.j2
dest: "{{ seaweed_config_dir }}/s3.json"
mode: '0644'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
- name: Install SeaweedFS services
template:
src: seaweed.service.j2
dest: "/etc/systemd/system/seaweed-{{ item.name }}.service"
mode: '0644'
owner: "{{ seaweed_user }}"
group: "{{ seaweed_group }}"
loop: "{{ seaweed_services }}"
vars:
seaweed_service: "{{ item.name }}"
seaweed_command: "{{ item.name }}"
seaweed_args: "{{ item.args }}"
- name: Reload systemd daemon
systemd:
daemon_reload: yes
- name: Enable and start SeaweedFS services
systemd:
name: "seaweed-{{ item.name }}"
enabled: yes
state: restarted
loop: "{{ seaweed_services }}"

View File

@ -0,0 +1,25 @@
# A sample TOML config file for SeaweedFS filer store
# Used with "weed filer" or "weed server -filer"
# Put this file to one of the location, with descending priority
# ./filer.toml
# $HOME/.seaweedfs/filer.toml
# /etc/seaweedfs/filer.toml
####################################################
# Customizable filer server options
####################################################
[filer.options]
# with http DELETE, by default the filer would check whether a folder is empty.
# recursive_delete will delete all sub folders and files, similar to "rm -Rf"
recursive_delete = false
#max_file_name_length = 255
####################################################
# The following are filer store options
####################################################
[leveldb2]
# local on disk, mostly for simple single-machine setup, fairly scalable
# faster than previous leveldb, recommended.
enabled = true
dir = "{{ seaweed_data_dir }}/filer/ldb2" # directory to store level db files

View File

@ -0,0 +1 @@
{{ seaweedfs_s3_config | default({}) | to_nice_json }}

View File

@ -0,0 +1,12 @@
[Unit]
Description=SeaweedFS - {{ seaweed_service }} Server
After=network.target
[Service]
ExecStart={{ seaweed_binary_path }} -logdir={{ seaweed_log_dir }} {{ seaweed_command }} {% for arg in seaweed_args %}{{ arg }} {% endfor +%}
User={{ seaweed_user }}
Restart=on-failure
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,132 @@
# Put this file to one of the location, with descending priority
# ./security.toml
# $HOME/.seaweedfs/security.toml
# /etc/seaweedfs/security.toml
# this file is read by master, volume server, and filer
# comma separated origins allowed to make requests to the filer and s3 gateway.
# enter in this format: https://domain.com, or http://localhost:port
[cors.allowed_origins]
values = "*"
# this jwt signing key is read by master and volume server, and it is used for write operations:
# - the Master server generates the JWT, which can be used to write a certain file on a volume server
# - the Volume server validates the JWT on writing
# the jwt defaults to expire after 10 seconds.
[jwt.signing]
key = "{{ seaweed_jwt_signing }}"
expires_after_seconds = 10 # seconds
# by default, if the signing key above is set, the Volume UI over HTTP is disabled.
# by setting ui.access to true, you can re-enable the Volume UI. Despite
# some information leakage (as the UI is not authenticated), this should not
# pose a security risk.
[access]
ui = false
# by default the filer UI is enabled. This can be a security risk if the filer is exposed to the public
# and the JWT for reads is not set. If you don't want the public to have access to the objects in your
# storage, and you haven't set the JWT for reads it is wise to disable access to directory metadata.
# This disables access to the Filer UI, and will no longer return directory metadata in GET requests.
[filer.expose_directory_metadata]
enabled = true
# this jwt signing key is read by master and volume server, and it is used for read operations:
# - the Master server generates the JWT, which can be used to read a certain file on a volume server
# - the Volume server validates the JWT on reading
# NOTE: jwt for read is only supported with master+volume setup. Filer does not support this mode.
[jwt.signing.read]
key = ""
expires_after_seconds = 10 # seconds
# If this JWT key is configured, Filer only accepts writes over HTTP if they are signed with this JWT:
# - f.e. the S3 API Shim generates the JWT
# - the Filer server validates the JWT on writing
# the jwt defaults to expire after 10 seconds.
[jwt.filer_signing]
key = "{{ seaweed_jwt_filer_signing }}"
expires_after_seconds = 10 # seconds
# If this JWT key is configured, Filer only accepts reads over HTTP if they are signed with this JWT:
# - f.e. the S3 API Shim generates the JWT
# - the Filer server validates the JWT on writing
# the jwt defaults to expire after 10 seconds.
[jwt.filer_signing.read]
key = ""
expires_after_seconds = 10 # seconds
# all grpc tls authentications are mutual
# the values for the following ca, cert, and key are paths to the PERM files.
# the host name is not checked, so the PERM files can be shared.
[grpc]
ca = "{{ seaweed_ca_cert }}"
# Set wildcard domain for enable TLS authentication by common names
allowed_wildcard_domain = "" # .mycompany.com
[grpc.volume]
cert = "{{ seaweed_volume_cert }}"
key = "{{ seaweed_volume_key }}"
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.master]
cert = "{{ seaweed_master_cert }}"
key = "{{ seaweed_master_key }}"
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.filer]
cert = "{{ seaweed_filer_cert }}"
key = "{{ seaweed_filer_key }}"
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.s3]
cert = "{{ seaweed_client_cert }}"
key = "{{ seaweed_client_key }}"
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.msg_broker]
cert = ""
key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
[grpc.msg_agent]
cert = ""
key = ""
allowed_commonNames = "" # comma-separated SSL certificate common names
# use this for any place needs a grpc client
# i.e., "weed backup|benchmark|filer.copy|filer.replicate|mount|s3|upload"
[grpc.client]
cert = "{{ seaweed_client_cert }}"
key = "{{ seaweed_client_key }}"
# https client for master|volume|filer|etc connection
# It is necessary that the parameters [https.volume]|[https.master]|[https.filer] are set
[https.client]
enabled = false
cert = ""
key = ""
ca = ""
# volume server https options
[https.volume]
cert = ""
key = ""
ca = ""
# master server https options
[https.master]
cert = ""
key = ""
ca = ""
# filer server https options
[https.filer]
cert = ""
key = ""
ca = ""
# disable_tls_verify_client_cert = true|false (default: false)
# white list. It's checking request ip address.
[guard]
white_list = ""

View File

@ -0,0 +1,41 @@
# Map architecture + large_disk flag to artifact name
asset_name_matrix:
x86_64:
full: "linux_amd64_full.tar.gz"
large_disk: "linux_amd64_large_disk.tar.gz"
aarch64:
full: "linux_arm64_full.tar.gz"
large_disk: "linux_arm64_large_disk.tar.gz"
armv7l:
full: "linux_arm_full.tar.gz"
large_disk: "linux_arm_large_disk.tar.gz"
seaweed_services:
- name: master
args:
- "-mdir={{ seaweed_data_dir}}/master"
- "-ip.bind={{ seaweed_master_bind }}"
- "-ip={{ seaweed_master_host }}"
- "-port={{ seaweed_master_port }}"
- name: volume
args:
- "-dir={{ seaweed_data_dir }}/volume"
- "-max={{ seaweed_volume_max }}"
- "-mserver={{ seaweed_master_host }}:{{ seaweed_master_port }}"
- "-ip.bind={{ seaweed_master_bind }}"
- "-ip={{ seaweed_master_host }}"
- "-port={{ seaweed_volume_port }}"
- name: filer
args:
- "-master={{ seaweed_master_host }}:{{ seaweed_master_port }}"
- "-ip.bind={{ seaweed_master_bind }}"
- "-ip={{ seaweed_master_host }}"
- "-port={{ seaweed_filer_port }}"
- "-localSocket={{ seaweed_data_dir }}/filer/seaweed-filer-{{ seaweed_filer_port }}.sock"
- name: s3
args:
- "-filer={{ seaweed_master_host }}:{{ seaweed_filer_port }}"
- "-ip.bind={{ seaweed_master_bind }}"
- "-port={{ seaweed_s3_port }}"
- "-localSocket={{ seaweed_data_dir }}/s3/seaweed-s3-{{ seaweed_s3_port }}.sock"
- "-config /etc/seaweedfs/s3.json"