Total Pageviews

Thursday, 28 September 2023

nostream

 A Nostr Relay written in TypeScript.

GitHub release GitHub issues GitHub stars GitHub top language GitHub forks GitHub license Coverage Status Sonarcloud quality gate Build status

This is a nostr relay, written in Typescript.

This implementation is production-ready. See below for supported features.

The project master repository is available on GitHub.

Deploy on Railway

Features

NIPs with a relay-specific implementation are listed here.

  • NIP-01: Basic protocol flow description
  • NIP-02: Contact list and petnames
  • NIP-04: Encrypted Direct Message
  • NIP-09: Event deletion
  • NIP-11: Relay information document
  • NIP-11a: Relay Information Document Extensions
  • NIP-12: Generic tag queries
  • NIP-13: Proof of Work
  • NIP-15: End of Stored Events Notice
  • NIP-16: Event Treatment
  • NIP-20: Command Results
  • NIP-22: Event created_at Limits
  • NIP-26: Delegated Event Signing
  • NIP-28: Public Chat
  • NIP-33: Parameterized Replaceable Events
  • NIP-40: Expiration Timestamp

Requirements

Standalone setup

  • PostgreSQL 14.0
  • Redis
  • Node v18
  • Typescript

Docker setups

  • Docker v20.10
  • Docker Compose v2.10

Local Docker setup

  • Docker Desktop v4.2.0 or newer
  • mkcert

WARNING: Docker distributions from Snap, Brew or Debian repositories are NOT SUPPORTED and will result in errors. Install Docker from their official guide ONLY.

Full Guide

Accepting Payments

  • Before you begin

    • Complete one of the Quick Start guides in this document
    • Create a .env file
    • On .nostr/settings.yaml file make the following changes:
      • Set payments.enabled to true
      • Set payments.feeSchedules.admission.enabled to true
      • Set limits.event.pubkey.minBalance to the minimum balance in msats required to accept events (i.e. 1000000 to require a balance of 1000 sats)
    • Choose one of the following payment processors: zebedee, nodeless, opennode, lnbits, lnurl
  • ZEBEDEE

    ZEBEDEE_API_KEY={YOUR_ZEBEDEE_API_KEY_HERE}
    
    • Follow the required steps for all payments processors
    • On .nostr/settings.yaml file make the following changes:
      • payments.processor to zebedee
      • paymentsProcessors.zebedee.callbackBaseURL to match your Nostream URL (e.g. https://{YOUR_DOMAIN_HERE}/callbacks/zebedee)
    • Restart Nostream (./scripts/stop followed by ./scripts/start)
    • Read the in-depth guide for more information: Set Up a Paid Nostr Relay with ZEBEDEE API
  • Nodeless

    • Complete the step "Before you begin"
    • Sign up for a new account, create a new store and take note of the store ID
    • Go to Profile > API Tokens and generate a new key and take note of it
    • Create a store webhook with your Nodeless callback URL (e.g. https://{YOUR_DOMAIN_HERE}/callbacks/nodeless) and make sure to enable all of the events. Grab the generated store webhook secret
    • Set NODELESS_API_KEY and NODELESS_WEBHOOK_SECRET environment variables with generated API key and webhook secret, respectively
    NODELESS_API_KEY={YOUR_NODELESS_API_KEY}
    NODELESS_WEBHOOK_SECRET={YOUR_NODELESS_WEBHOOK_SECRET}
    
    • On your .nostr/settings.yaml file make the following changes:
      • Set payments.processor to nodeless
      • Set paymentsProcessors.nodeless.storeId to your store ID
    • Restart Nostream (./scripts/stop followed by ./scripts/start)
  • OpenNode

    • Complete the step "Before you begin"

    • Sign up for a new account and get verified

    • Go to Developers > Integrations and setup two-factor authentication

    • Create a new API Key with Invoices permission

    • Set OPENNODE_API_KEY environment variable on your .env file

      OPENNODE_API_KEY={YOUR_OPENNODE_API_KEY}
      
    • On your .nostr/settings.yaml file make the following changes:

      • Set payments.processor to opennode
    • Restart Nostream (./scripts/stop followed by ./scripts/start)

  • LNBITS

    • Complete the step "Before you begin"

    • Create a new wallet on you public LNbits instance

      • Demo server must not be used for production
      • Your instance must be accessible from the internet and have a valid SSL/TLS certificate
    • Get wallet Invoice/read key (in Api docs section of your wallet)

    • set LNBITS_API_KEY environment variable with the Invoice/read key Key above on your .env file

      LNBITS_API_KEY={YOUR_LNBITS_API_KEY_HERE}
      
      • On your .nostr/settings.yaml file make the following changes:

        • Set payments.processor to lnbits
        • set lnbits.baseURL to your LNbits instance URL (e.g. https://{YOUR_LNBITS_DOMAIN_HERE}/)
        • Set paymentsProcessors.lnbits.callbackBaseURL to match your Nostream URL (e.g. https://{YOUR_DOMAIN_HERE}/callbacks/lnbits)
      • Restart Nostream (./scripts/stop followed by ./scripts/start)

    1. Alby or any LNURL Provider with LNURL-verify support

      • Complete the step "Before you begin"
      • Create a new account if you don't have an LNURL
      • On your .nostr/settings.yaml file make the following changes:
        • Set payments.processor to lnurl
        • Set lnurl.invoiceURL to your LNURL (e.g. https://getalby.com/lnurlp/your-username)
      • Restart Nostream (./scripts/stop followed by ./scripts/start)
    2. Ensure payments are required for your public key

      • Visit https://{YOUR-DOMAIN}/
      • You should be presented with a form requesting an admission fee to be paid
      • Fill out the form and take the necessary steps to pay the invoice
      • Wait until the screen indicates that payment was received
      • Add your relay URL to your favorite Nostr client (wss://{YOUR-DOMAIN}) and wait for it to connect
      • Send a couple notes to test
      • Go to https://websocketking.com/ and connect to your relay (wss://{YOUR_DOMAIN})
      • Convert your npub to hexadecimal using a Key Converter
      • Send the following JSON message: ["REQ", "payment-test", {"authors":["your-pubkey-in-hexadecimal"]}]
      • You should get back the few notes you sent earlier

    Quick Start (Docker Compose)

    Install Docker following the official guide. You may have to uninstall Docker if you installed it using a different guide.

    Clone repository and enter directory:

    git clone git@github.com:Cameri/nostream.git
    cd nostream
    

    Generate a secret with: openssl rand -hex 128 Copy the output and paste it into an .env file:

    SECRET=aaabbbccc...dddeeefff
    # Secret shortened for brevity
    

    Start:

    ./scripts/start
    

    or

    ./scripts/start_with_tor
    

    Stop the server with:

    ./scripts/stop
    

    Print the Tor hostname:

    ./scripts/print_tor_hostname
    

    Running as a Service

    By default this server will run continuously until you stop it with Ctrl+C or until the system restarts.

    You can install as a systemd service if you want the server to run again automatically whenever the system is restarted. For example:

    $ nano /etc/systemd/system/nostream.service
    
    # Note: replace "User=..." with your username, and
    # "/home/nostr/nostream" with the directory where you cloned the repo.
    
    [Unit]
    Description=Nostr TS Relay
    After=network.target
    StartLimitIntervalSec=0
    
    [Service]
    Type=simple
    Restart=always
    RestartSec=5
    User=nostr
    WorkingDirectory=/home/nostr/nostream
    ExecStart=/home/nostr/nostream/scripts/start
    ExecStop=/home/nostr/nostream/scripts/stop
    
    [Install]
    WantedBy=multi-user.target
    

    And then:

    systemctl enable nostream
    systemctl start nostream
    

    The logs can be viewed with:

    journalctl -u nostream
    

    Quick Start (Standalone)

    Set the following environment variables:

    DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test"
    DB_USER=postgres
    

    or

    DB_HOST=localhost
    DB_PORT=5432
    DB_NAME=nostr_ts_relay
    DB_USER=postgres
    DB_PASSWORD=postgres
    
    REDIS_URI="redis://default:nostr_ts_relay@localhost:6379"
    
    REDIS_HOST=localhost
    REDIS_PORT=6379
    REDIS_USER=default
    REDIS_PASSWORD=nostr_ts_relay
    

    Generate a long random secret and set SECRET: You may want to use openssl rand -hex 128 to generate a secret.

    SECRET=aaabbbccc...dddeeefff
    # Secret shortened for brevity
    

    Initializing the database

    Create nostr_ts_relay database:

    $ psql -h $DB_HOST -p $DB_PORT -U $DB_USER -W
    postgres=# create database nostr_ts_relay;
    postgres=# quit
    

    Start Redis and use redis-cli to set the default password and verify:

    $ redis-cli
    127.0.0.1:6379> CONFIG SET requirepass "nostr_ts_relay"
    OK
    127.0.0.1:6379> AUTH nostr_ts_relay
    Ok
    

    Clone repository and enter directory:

    git clone git@github.com:Cameri/nostream.git
    cd nostream
    

    Install dependencies:

    npm install -g knex
    npm install
    

    Run migrations (at least once and after pulling new changes):

    NODE_OPTIONS="-r dotenv/config" npm run db:migrate
    

    Create .nostr folder inside nostream project folder and copy over the settings file:

    mkdir .nostr
    cp resources/default-settings.yaml .nostr/settings.yaml
    

    To start in development mode:

    npm run dev
    

    Or, start in production mode:

    npm run start
    

    To clean up the build, coverage and test reports run:

    npm run clean
    

    Development Quick Start (Docker Compose)

    Install Docker Desktop following the official guide. You may have to uninstall Docker on your machine if you installed it using a different guide.

    Clone repository and enter directory:

    git clone git@github.com:Cameri/nostream.git
    cd nostream
    

    Start:

    ./scripts/start_local
    

    This will run in the foreground of the terminal until you stop it with Ctrl+C.

    Tests

    Unit tests

    Open a terminal and change to the project's directory:

    cd /path/to/nostream
    

    Run unit tests with:

    npm run test:unit
    

    Or, run unit tests in watch mode:

    npm run test:unit:watch
    

    To get unit test coverage run:

    npm run cover:unit
    

    To see the unit tests report open .test-reports/unit/index.html with a browser:

    open .test-reports/unit/index.html
    

    To see the unit tests coverage report open .coverage/unit/lcov-report/index.html with a browser:

    open .coverage/unit/lcov-report/index.html
    

    Integration tests (Docker Compose)

    Open a terminal and change to the project's directory:

    cd /path/to/nostream
    

    Run integration tests with:

    npm run docker:test:integration
    

    And to get integration test coverage run:

    npm run docker:cover:integration
    

    Integration tests (Standalone)

    Open a terminal and change to the project's directory:

    cd /path/to/nostream
    

    Set the following environment variables:

    DB_URI="postgresql://postgres:postgres@localhost:5432/nostr_ts_relay_test"
    
    or
    
    DB_HOST=localhost
    DB_PORT=5432
    DB_NAME=nostr_ts_relay_test
    DB_USER=postgres
    DB_PASSWORD=postgres
    DB_MIN_POOL_SIZE=1
    DB_MAX_POOL_SIZE=2
    

    Then run the integration tests:

    npm run test:integration
    

    To see the integration tests report open .test-reports/integration/report.html with a browser:

    open .test-reports/integration/report.html
    

    To get the integration test coverage run:

    npm run cover:integration
    

    To see the integration test coverage report open .coverage/integration/lcov-report/index.html with a browser.

    open .coverage/integration/lcov-report/index.html
    

    Configuration

    You can change the default folder by setting the NOSTR_CONFIG_DIR environment variable to a different path.

    Run nostream using one of the quick-start guides at least once and nostream/.nostr/settings.json will be created. Any changes made to the settings file will be read on the next start.

    Default settings can be found under resources/default-settings.yaml. Feel free to copy it to nostream/.nostr/settings.yaml if you would like to have a settings file before running the relay first.

    See CONFIGURATION.md for a detailed explanation of each environment variable and setting.

    Dev Channel

    For development discussions, please use the Nostr Typescript Relay Dev Group.

    For discussions about the protocol, please feel free to use the Nostr Telegram Group.

    Author

    I'm Cameri on most social networks. You can find me on Nostr by npub1qqqqqqyz0la2jjl752yv8h7wgs3v098mh9nztd4nr6gynaef6uqqt0n47m.

    from https://github.com/Cameri/nostream 

    (https://github.com/nostr-protocol/nostr)

    --------------------------------------------------

    nostr 是一个相当简单的开放协议,可以在全球范围内搭建一个有趣的社交网络。因为协议本身很简单,所以大部分的加密、签名工作在客户端完成,而中继服务器 Relay 所做的事情只是接收事件消息,根据客户端订阅要求返回消息。

    目前 relay 的实现也很多,比如 nostream 的搭建就很方便,只要安装好 docker,设置好域名,直接运行就可以啦。

    以下记录一下 Relay 的搭建过程。

    1. 安装基础软件

    首先分配一台安装 Ubuntu Server 20.04 LTS Ubuntu Server 20.04 LTS 操作系统的虚拟机,默认规格就够了。

    首先,更新软件包列表。提示 30 个软件包需要升级,暂时先不管。

    kimim@nostr:~$ sudo apt update
    
    # update package list from mirrors
    Fetched 25.5 MB in 4s (6240 kB/s)
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    30 packages can be upgraded. Run 'apt list --upgradable' to see them.
    

    然后,安装以下软件包,用来运行编译 nostream,配置 relay 的证书。

    kimim@nostr:~$ sudo apt install nodejs npm nginx certbot python3-certbot-nginx
    
    # list of packages need to be installed
    0 upgraded, 410 newly installed, 0 to remove and 30 not upgraded.
    Need to get 168 MB of archives.
    After this operation, 669 MB of additional disk space will be used.
    Do you want to continue? [Y/n] Y
    # installation in progress
    

    2. 安装 docker

    接下来,安装 docker,因为根据 nostream 官网要求,需要安装官方的 docker。就是按照 https://docs.docker.com/engine/install/ubuntu/ 安装 docker。

    首先,删除已经安装的 docker(如果有,我的这台机器刚初始化,所以没有安装 docker)。

    kimim@nostr:~$ sudo apt-get remove docker.io
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    Package 'docker.io' is not installed, so not removed
    0 upgraded, 0 newly installed, 0 to remove and 30 not upgraded.
    

    然后,安装 docker 需要的证书组件。

    kimim@nostr:~$ sudo apt-get install ca-certificates curl gnupg lsb-release
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    lsb-release is already the newest version (11.1.0ubuntu4).
    lsb-release set to manually installed.
    ca-certificates is already the newest version (20211016ubuntu0.22.04.1).
    ca-certificates set to manually installed.
    curl is already the newest version (7.81.0-1ubuntu1.7).
    curl set to manually installed.
    gnupg is already the newest version (2.2.27-3ubuntu2.1).
    gnupg set to manually installed.
    0 upgraded, 0 newly installed, 0 to remove and 30 not upgraded.
    

    接着,添加 docker 官方 GPG 证书。

    kimim@nostr:~$ sudo mkdir -p /etc/apt/keyrings
    kimim@nostr:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    

    添加 docker 官方源:

    kimim@nostr:~$ echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    

    再次更新软件包:

    kimim@nostr:~$ sudo apt-get update
    Get:1 https://download.docker.com/linux/ubuntu jammy InRelease [48.9 kB]
    Get:2 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages [12.7 kB]
    Fetched 61.6 kB in 1s (105 kB/s)
    Reading package lists... Done
    

    安装 docker 以及 cli,compose 插件。

    kimim@nostr:~$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
    
    # list of packages need to be installed
    0 upgraded, 11 newly installed, 0 to remove and 30 not upgraded.
    Need to get 111 MB of archives.
    After this operation, 397 MB of additional disk space will be used.
    Do you want to continue? [Y/n] Y
    
    # installation in progress
    

    把当前用户添加到 docker 权限组:

    kimim@nostr:~$ sudo usermod -a -G docker kimim
    kimim@nostr:~$ newgrp docker
    

    测试一下 docker 是否正常工作:

    kimim@nostr:~$ docker run hello-world
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    2db29710123e: Pull complete
    Digest: sha256:aa0cc8055b82dc2509bed2e19b275c8f463506616377219d9642221ab53cf9fe
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    

    3. 配置服务器证书

    修改 nginx 的配置文件。请根据自己的服务器域名修改 server_name 字段。

    kimim@nostr:~$ sudo rm -rf /etc/nginx/sites-available/default
    kimim@nostr:~$ sudo vi /etc/nginx/sites-available/default
    # 添加以下内容
    kimim@nostr:~$ cat /etc/nginx/sites-available/default
    server{
        server_name nostr.kimi.im;
        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_pass http://127.0.0.1:8008;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
    

    重启 nginx,使配置生效。

    kimim@nostr:~$ sudo service nginx restart
    

    添加 A 域名记录,比如:

    TYPE    HOST            ANSWER          TTL
    A       nostr.kimi.im   192.30.252.153  300
    

    等一两分钟,等域名记录生效,再用 certbox 配置服务器证书:

    kimim@nostr:~$ sudo certbot --nginx -d nostr.kimi.im
    Saving debug log to /var/log/letsencrypt/letsencrypt.log
    Enter email address (used for urgent renewal and security notices)
     (Enter 'c' to cancel): kimim@kimi.im
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Please read the Terms of Service at
    https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
    agree in order to register with the ACME server. Do you agree?
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: Y
    
    Successfully received certificate.
    Certificate is saved at: /etc/letsencrypt/live/nostr.kimi.im/fullchain.pem
    Key is saved at:         /etc/letsencrypt/live/nostr.kimi.im/privkey.pem
    This certificate expires on 2023-05-05.
    These files will be updated when the certificate renews.
    Certbot has set up a scheduled task to automatically renew this certificate in the background.
    
    Deploying certificate
    Successfully deployed certificate for nostr.kimi.im to /etc/nginx/sites-enabled/default
    Congratulations! You have successfully enabled HTTPS on https://nostr.kimi.im
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    If you like Certbot, please consider supporting our work by:
     * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
     * Donating to EFF:                    https://eff.org/donate-le
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    

    4. 运行 nostream

    获取 nostream 代码:

    kimim@nostr:~$ git clone https://github.com/Cameri/nostream.git
    Cloning into 'nostream'...
    remote: Enumerating objects: 3287, done.
    remote: Counting objects: 100% (1228/1228), done.
    remote: Compressing objects: 100% (415/415), done.
    remote: Total 3287 (delta 889), reused 984 (delta 803), pack-reused 2059
    Receiving objects: 100% (3287/3287), 1.05 MiB | 7.90 MiB/s, done.
    Resolving deltas: 100% (2036/2036), done.
    

    用 docker 运行 nostream,大概用了两分钟,就看到一个漂亮的 NOSTREAM logo 了。

    kimim@nostr:~$ cd nostream/
    kimim@nostr:~/nostream$ npm run docker:compose:start
    > nostream@1.21.0 docker:compose:start
    > ./scripts/start
    
    [+] Running 25/25
    # ...
    [+] Building 128.2s (16/16) FINISHED
    # ...
    [+] Running 6/5
    # ...
    Attaching to nostream, nostream-cache, nostream-db, nostream-migrate
    # ...
    nostream-db       | CREATE DATABASE
    # ...
    nostream          |
    nostream          |  ███▄    █  ▒█████    ██████ ▄▄▄█████▓ ██▀███  ▓█████ ▄▄▄       ███▄ ▄███▓
    nostream          |  ██ ▀█   █ ▒██▒  ██▒▒██    ▒ ▓  ██▒ ▓▒▓██ ▒ ██▒▓█   ▀▒████▄    ▓██▒▀█▀ ██▒
    nostream          | ▓██  ▀█ ██▒▒██░  ██▒░ ▓██▄   ▒ ▓██░ ▒░▓██ ░▄█ ▒▒███  ▒██  ▀█▄  ▓██    ▓██░
    nostream          | ▓██▒  ▐▌██▒▒██   ██░  ▒   ██▒░ ▓██▓ ░ ▒██▀▀█▄  ▒▓█  ▄░██▄▄▄▄██ ▒██    ▒██
    nostream          | ▒██░   ▓██░░ ████▓▒░▒██████▒▒  ▒██▒ ░ ░██▓ ▒██▒░▒████▒▓█   ▓██▒▒██▒   ░██▒
    nostream          | ░ ▒░   ▒ ▒ ░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░  ▒ ░░   ░ ▒▓ ░▒▓░░░ ▒░ ░▒▒   ▓▒█░░ ▒░   ░  ░
    nostream          | ░ ░░   ░ ▒░  ░ ▒ ▒░ ░ ░▒  ░ ░    ░      ░▒ ░ ▒░ ░ ░  ░ ▒   ▒▒ ░░  ░      ░
    nostream          |    ░   ░ ░ ░ ░ ░ ▒  ░  ░  ░    ░        ░░   ░    ░    ░   ▒   ░      ░
    nostream          |          ░     ░ ░        ░              ░        ░  ░     ░  ░       ░
    nostream          |                                   v1.21.0
    nostream          |           NIPs implemented: 1,2,4,9,11,12,15,16,20,22,26,28,33,40
    nostream          |                            Pay-to-relay disabled
    nostream          |                          Payments provider: zebedee
    nostream          |                           2 client workers started
    nostream          |                         1 maintenance worker started
    nostream          |                         Tor hidden service: disabled
    

    5. 用 noscl 测试 relay 是否正常工作

    删除之前添加的 relay:

    [kimim@virtualbox Desktop]$ ./noscl relay
    wss://nos.lol: rw
    [kimim@virtualbox Desktop]$ ./noscl relay remove wss://nos.lol
    Removed relay wss://nos.lol.
    

    添加刚刚搭建的 relay:

    [kimim@virtualbox Desktop]$ ./noscl relay add wss://nostr.kimi.im
    Added relay wss://nostr.kimi.im.
    

    发送消息 Bonjour tout le monde:

    [kimim@virtualbox Desktop]$ ./noscl publish "Bonjour tout le monde"
    Sent event a170e3f3c4f8cfb79cacccf28d5f7d51a5e17b4e40c0984593a692b83f9cf43c to 'wss://nostr.kimi.im'.
    Seen a170e3f3c4f8cfb79cacccf28d5f7d51a5e17b4e40c0984593a692b83f9cf43c on 'wss://nostr.kimi.im'.
    

    在 Damus 一开始收不测试帐号发送的消息,需要在 Damus 客户端也添加同样的 relay。

    然后就能看到测试帐号发的:Bonjour tout le monde

     

     

     


     

    如何将项目部署至 Tomcat 的根下

     

    有两种方法可以实现将项目部署到 Tomcat 的根下。

    1. 删掉自带的 ROOT / 目录,然后将项目的 war 包重命名为 ROOT.war

    2. 将项目正常部署 (假设 war 包名为 your_project.war),然后修改 conf/server.xml 中的 Context Root为如下内容:

    <Context path="" docBase="your_project" debug="0" reloadable="true"></Context>

    参考文献:https://stackoverflow.com/questions/5328518/deploying-my-application-at-the-root-in-tomcat

    解决 Maven 的 unable to find valid certification path to requested target 错误

     

    今天我在从公司的 Maven私库下载依赖时,Maven 报出了 unable to find valid certification path to requested target 的问题,经查询是因为没有将私库使用的自签名证书导入到 Java 的 keystore。这里写一下我的两个解决方案,方便发生了同样问题的人参考。

    让 Maven 忽略证书错误

    因为在默认情况下,自签名证书是不受信任的,那么我们只要让 Maven 忽略证书错误,就可以解决这个问题了。

    我们可以在.bashrc.zshrc(或者其他位置,看你用哪个 shell 了)里面加入如下语句:

    export MAVEN_OPTS='-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Djsse.enableSNIExtension=false'

    或者,也可以在 ~/.mavenrc 中配置这个参数:

    MAVEN_OPTS="-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Djsse.enableSNIExtension=false"

    导入证书到 keystore

    首先使用这个命令得到网站上面的证书:

    # 注意将mavenrepository.mycompany.com替换成实际的地址
    openssl s_client -showcerts -connect mavenrepository.mycompany.com:443

    在输出中可以看到类似这样的证书信息:

    s:/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Red Hat Network/CN=Entitlement Master CA/emailAddress=ca-support@redhat.com

    i:/C=US/ST=North Carolina/L=Raleigh/O=Red Hat, Inc./OU=Red Hat Network/CN=Entitlement Master CA/emailAddress=ca-support@redhat.com

    我们要在这里面寻找 issuer(i:)subject(s:) 相同的证书,这个就是我们要导出的根证书。找到之后,保存证书的哈希(即以 —–BEGIN CERTIFICATE—–开始,以 —–END CERTIFICATE—–结束的这部分内容)到一个文件中,比如 root.crt

    接下来,我们需要使用 keytool 把这个证书导入到 Java 的 keystore 中,命令如下:

    sudo keytool \
    -importcert \
    # keystore文件位置需要修改成实际的位置
    -keystore /usr/local/java/jdk1.8.0_60/jre/lib/security/cacerts \
    # keystore密码需要修改成实际的密码,默认密码是changeit
    -storepass changeit \
    # 要导入的证书,就是刚才保存的那个,注意使用实际的位置
    -file ~/Downloads/root.crt \
    # 给证书起个名字
    -alias "mavenrepository-mycompany"

    执行后 keytool 会询问是否信任这个证书,输入 yes 来信任。

    导入完成后,Maven 就可以从这个私库下载依赖了。如果你使用 IDEA 的话,那么可能需要重新启动一下 IDEA 才会使新的 keystore 生效。

    [^1]: How to resolve “unable to find valid certification path to requested target” error? - JFrog


    [^2]: How to tell Maven to disregard SSL errors (and trusting all certs)?

    使用 SSH config 简化 SSH连接

     

    如果你有很多的服务器要连接,如果对你来说记住那些服务器的地址、端口实在是一种痛苦,如果你一直在寻找一种能够简化在命令行下连接 SSH 服务器的办法,那么,本文将给你提供一种解决问题的思路,那就是,使用 SSH 的 config 文件。

    SSH config 文件是什么

    Open SSH 客户端配置文件,允许你以配置项的形式,记录各个服务器的连接信息,并允许你使用一个定义好的别名来代替其对应的 ssh 命令参数。

    SSH config 文件该怎么用

    创建 SSH config 文件

    通常来说,该文件会出现在两个地方,一个是 /etc/ssh/ssh_config,一个是 ~/.ssh/config

    /etc/ssh/ssh_config 文件通常用来定义全局范围上的 SSH 客户端参数,而 ~/.ssh/config 则被用来定义每个用户自己的 SSH 客户端的配置。我们将要修改的,就是位于用户目录下的 config 文件。

    如果 ~/.ssh/config 文件不存在,那么也不用着急,这是正常的,只需要执行如下命令,即可新建一个空白的 config 文件

    touch ~/.ssh/config

    编写 config 条目

    假如说,我们想连接到一台服务器,它的地址是 example.server.com,端口号是 2222,以用户 admin 登陆,并使用~/.ssh/id_rsa 这个私钥验证身份。那么,我们需要在命令行里输入:

    ssh admin@example.server.com -p 2222 -i ~/.ssh/id_rsa

    嗯好吧,-i 参数可以省略,但即使这样,命令还是很长,对吧?

    那么我们把这个服务器的连接参数写到 config 文件里,就变成了这个样子:

    # 此处我为了美观起见,给每个子条目都缩进了一层,实际使用时缩进不影响文件的效果。

    Host sample
    Hostname example.server.com
    Port 2222
    User admin
    Identityfile ~/.ssh/id_rsa

    嗯,在这里,它还有了一个新名字,叫 sample

    然后,我们只需要:

    ssh sample

    就可以连接到这台主机了。

    创建通配符规则

    有的时候,我们需要连接多台不同的主机,那难道我们需要针对每个主机都写一遍规则吗?

    答案是不一定。如果你要连接的主机,它们的域名有一定规律可循,那么我们可以用通配符来匹配这一系列的主机。

    比如,公司里针对开发和测试环境,各创建了一系列集群,同时各个集群中又根据负责的业务不同,有多台负载均衡的主机,那么我们可以这样写:

    # 首先匹配所有主机,在这里配置好我们的用户名、私钥等参数
    Host *
    User boris1993
    IdentityFile ~/.ssh/id_rsa

    # 开发环境
    Host dev-*
    HostName %h.dev.mycompany.com

    # 测试环境
    Host staging-*
    HostName %h.staging.mycompany.com

    接下来,我们只需要执行类似 ssh dev-user,就可以连接到开发环境的负责用户管理的服务器上了。

    而实现这个操作的重点,我想你已经注意到了,一个是 Host 配置中的 *,另一个就是配置文件里面的 %h。星号我们都知道,是个通配符,放在这里就意味着它会匹配所有以 dev-* 开头的主机名;而 %h 是一个占位符,它会把你在 SSH 命令中 destination 部分的输入取出来放在这里,所以当我们执行 ssh dev-user 的时候,实际上命令会被展开成 ssh dev-user.dev.mycompany.com

    配置通过跳板机连接

    如果公司规定所有服务器都需要先 SSH 到跳板机,然后才能连接到具体的服务器,那该怎么办?把 ssh_config 文件放在跳板机上吗?

    确实这是一个解决方案,但不是唯一解。因为我们还有一个配置参数叫 ProxyJump。它,就是用来指定,在连接这个服务器之前,需要通过哪个跳板机。

    写起来,是这样的:

    # 其他部分略

    # 跳板机
    Host bastion
    HostName bastion.mycompany.com

    # 服务器
    Host dev-*
    HostName %h.dev.mycompany.com
    ProxyJump bastion

    如果你的 SSH 版本早于 7.3,那么很可惜它是不支持 ProxyJump 这条配置的。但是不要灰心,它支持另一条配置,ProxyCommand

    # 其他部分略

    # 跳板机
    Host bastion
    HostName bastion.mycompany.com

    # 服务器
    Host dev-*
    HostName %h.dev.mycompany.com
    ProxyCommand ssh -W %h:%p bastion

    然后,我们继续执行 ssh dev-user 就可以了,SSH 会自动先连接到跳板机,然后在跳板机中再连接到我们要去的服务器。

    如果你们公司安全做的非常好,需要通过数个跳板机来连接服务器,那么只需要给每个跳板机都配置上更外层的跳板就好了,像这样:

    # 其他部分略

    # 最外层跳板机
    Host bastion-outer
    HostName bastion-outer.mycompany.com

    # 下一层跳板机
    Host bastion-inner
    HostName bastion-inner.mycompany.com
    ProxyJump bastion-outer

    # 服务器
    Host dev-*
    HostName %h.dev.mycompany.com
    ProxyJump bastion-inner

    这样,SSH 就会先连接到 bastion-outer,然后连到 bastion-inner,然后连到 dev-user。理论上,你可以在这里无限套娃(逃

    这玩意有意思,我还想了解更多!

    好吧,为了满足你的好奇心,我这里为你提供了 3 篇博客供你参考。当然,这三篇博客也是我编写本文时的参考文档:

    多个 SSH KEY 的管理

    How To Configure Custom Connection Options for your SSH Client

    Simplify Your Life With an SSH Config File

    另外,您也可以阅读 ssh_config 的手册页,来获得最原始的信息,阅读该手册的命令是:

    man ssh_config
    ------------------------------------------------------------

    为Git设置SSH公钥及私钥

    在使用 Git 进行代码管理时,如果我们不使用 SSH 公钥及密钥,那么我们就必须在每次执行 Git 命令后键入密码来验明正身,所以为 Git 配置 SSH 公钥及密钥是很有必要的。下文对 Windows 及 Linux 系统,自建 Git 及 Github 均适用。
    配置公钥

    首先通过 ssh-keygen -t rsa -b 4096 -C "name@example.com" 或者 XShell 的相应功能来生成一对密钥和公钥。随后我们得到了一个 id_rsa 和 id_rsa.pub (名称来源于你的定义,本文统一视作 id_rsa),其中 id_rsa 为私钥,id_rsa.pub 为公钥,我们需要把这个公钥的内容上传到服务器对应 Git 用户的 .ssh/authorized_keys 目录中,并在 SSH 的配置文件中允许通过公钥登陆。对于 Github 来说则是上传到 Github 中的公钥设置页面中。如果遇到提示未在远程服务器注册的问题,请执行 chmod 600 authorized_keys 。至此公钥配置完毕。
    配置私钥

    私钥则需要在客户端也就是我们自己的计算机上进行配置。无论你使用 Windows 还是 Linux,私钥都应该放置于用户账户目录下的 .ssh 中,对于 Windows 则是 C:\Users\用户名\.ssh ,对于 Linux 则是 /home/用户名/.ssh 中。

    随后我们在 .ssh 目录下新建一个 config 文件,将以下内容写入该文件:

    Host 远程服务器域名或IP
    User 登陆用的Git用户名
    PreferredAuthentications publickey
    IdentityFile /c/Users/用户名/.ssh/id_rsa

    这样一来就可以在客户端直接使用 Git 而无须输入密码了。
    多个 Git 服务器的密钥配置

    我们经常会同时使用多个不同的 Git 服务器,例如同时使用 Github 和 自建 Git 服务。虽然我们可以使用同一对私钥和公钥来连接所有 Git 服务器,但是这有较大的安全风险。因此我们需要为每台 Git 服务器生成不同的公钥及私钥,然后在每个 Git 服务器上按上文配置公钥,在客户端中通过向 config 文件添加多个 Host 来解决这一问题。实例如下:

    Host 192.168.1.10
    User git
    PreferredAuthentications publickey
    IdentityFile /c/Users/用户名/.ssh/id_rsa_a

    Host 192.168.1.11
    User git
    PreferredAuthentications publickey
    IdentityFile /c/Users/用户名/.ssh/id_rsa_b

    Windows 下配置 Git 私钥的注意事项

        由于 Windows 的目录也就是文件夹名称是允许空格存在的,而 Windows 下的 Git 客户端都是按照 Linux 的无空格标准来执行的,所以你的私钥如果保存到了带空格的文件夹下,就无法正常使用私钥登陆。此时只要把私钥移动至路径无空格的目录下,然后修改 config 文件中的 IdentityFile 为新路径即可。
        IdentityFile 的值需要填写 Linux 下的路径格式,如 /c/Users/eason/.ssh
    而不能是 windows 下的 C:\Users\eason\.ssh


     
     

     

    如何允许非root进程绑定低位端口

     

    众所周知,在Linux中,要想绑定端口号在1024以下的低位端口,是需要root权限的。但是,如果我又想绑定低位端口,又不想以root身份运行程序,该怎么办?答案是,setcap命令。

    一、使用条件

    1、您的Linux内核版本至少为2.6.24。

    2、文件不能是脚本。也就是说你必须将CAP_NET_BIND_SERVICE功能应用到可执行文件本身,而不是脚本中指向的其他应用。如果赋予了该文件CAP_NET_BIND_SERVICE能力,其他应用滥用用这个文件就可能在安全性上造成隐患。

    3、如果你的程序使用自己的.../lib/的共享库,而Linux将在任何具有像setcap或suid这样的特权提升的程序上禁用LD_LIBRARY_PATH,将导致不能使用。

    二、实现方法

    使用如下命令给这个程序附加CAP_NET_BIND_SERVICE权限即可。注意,这条命令需要以root身份执行:

    sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary

    三、实现原理

    接下来,我就把上面这条命令一点点拆开,解释清楚它到底干了什么。

    1、Capabilities

    首先介绍一下capabilities。在Linux内核版本2.2开始,Linux将一系列的超级管理员权限细分成了一个个可以单独开启关闭的单元,以提供更细粒度的权限控制,这些单元,就被称之为capabilities。详细的capabilities列表可以参考Man Page Capabilities(7)

    2、CAP_NET_BIND_SERVICE

    CAP_NET_BIND_SERVICE是Linux系统中超级管理员权限的细分单元,拥有CAP_NET_BIND_SERVICE能力的程序,就可以绑定端口号在 1024以下的特权端口。

    3、setcap

    那么,该如何设置CAP_NET_BIND_SERVICE呢?答案就是setcap命令。上文所提到的命令,就是给指定的这个二进制程序增加CAP_NET_BIND_SERVICE权限。

    在CAP_NET_BIND_SERVICE后面,用=+相连接的,则是开启CAP_NET_BIND_SERVICE的模式。模式有如下三种:

    e:Effective,意为这个能力是启用的。

    p:Permitted,意为这个能力是允许被使用的。

    i:inherited,意为这个能力可以被其子进程继承。

    在 setcap命令中,使用加号来开启这个模式,或者使用减号来关闭这个模式。

    4、查询某个程序拥有的权限

    getcap /path/to/binary
    #例如查询ping命令拥有的权限
    getcap /bin/ping
    /bin/ping = cap_net_raw+ep

    5、清除某个程序拥有的权限

    setcap -r /path/to/binary

    四、守护进程使用低位端口

    当某个程序当做守护进程运行,需要使用1024以下的低位端口时,无须使用步骤二的方法实现。可以在service的配置文件中指定 capabilities:

    [Service]
    # 该服务仅可以使用哪些capabilities
    CapabilityBoundingSet=CAP_NET_BIND_SERVICE
    # 以非root用户运行程序时需要设定此参数
    AmbientCapabilities=CAP_NET_BIND_SERVICE

    参考资料

    1. Man Page Capabilities(7)
    2. Man Page setcap(8)
    3. Man Page cap_from_text(3)
    4. getcap, setcap and file capabilities - insecure.ws
    5. Is there a way for non-root processes to bind to “privileged” ports on Linux? - Stack Overflow
    6. Linux 的 capabilities 机制


    Wednesday, 27 September 2023

    许家印被带走, 恒大帝国轰然倒塌

    —28/09/2023

    9月27日传出深陷债务危机的恒大集团主席许家印被警方带走的消息,彭博援引知情人士称,本月早些时候,许已被置于警方控制之下,根据中国『刑事诉讼法』,许应交出护照和身份证,不得离开居住地,不得与他人会面与联系。搜狐网更引据消息报道,许家印被“上铐带走”。

    搜狐网消息称,许家印被带走当日,广州市公安局天河区分局的警车出现在他位于珠江新城的办公室附近,有目击者表示,许家印甚至被戴上了手铐。彭博周三的报道说,知情人士表示许家印现在位于北京一处居所被监视居住。许家印被带走似乎只是时间问题。根据中国财新网英文版24日报道,恒大的二号人物、前首席执行官夏海钧、首席财务官潘大荣也已被控制或带走。在此之前,恒大集团前执行总裁柯鹏于今年一月被警方带走调查,柯鹏涉及深圳的旧改项目,曾经被视为恒大最重要的“压舱石” 。此外,被视为许家印“钱袋子”、为恒大提供融资的恒大财富总经理杜亮等人16日被深圳公安采取刑事强制措施,恒大人寿前董事长朱家麟21日传出被调查。中央社援引中国钛媒体分析,夏海钧等人被控制是一个非常明显的信号,恒大的融资管道被官方封堵,债务重组也被搁置,显示当局开始收网。另一家中国媒体北向财经分析称,恒大财富负责人杜亮16日被警方采取强制措施;恒大债务重组会议22日被搁置;恒大24日公告无法满足新票据的发行资格,“如同三把利剑,每一把都直指恒大的命门。”许家印只有“坐以待毙”了。该报道分析,恒大帝国将轰然倒塌,累累废墟之下,是无数普通人的血汗,这一切应该有人负责。恒大下地狱的过程时不时成为海内外媒体头条,六月底,该集团的债务估计已高达3280亿美元,是世界债务最高的房地产开发商。两年来,恒大集团引爆信任危机,这一曾经叱诧风云的房地产帝国,在中国经济低迷、银行收紧信贷后,一步步 走向崩溃。法新社报道说,仅仅几年前,2017年,许家印是亚洲最富有的人,拥有财富预估453亿美元。自从恒大陷入危机,根据胡润亿万富翁排行榜,许家印的财富在2022年大幅缩水至43亿美元。许家印被警方带走的消息尚未得到官方证实,但已使恒大的股值狂泻。周三,在香港上市的恒大股值暴跌近19%。这一消息来得不是时候,因为中国即将迎来为期一周的国庆假期,而国庆假期通常有利于房地产购买。出身于伐木工人之家,曾经是亚洲第二富豪,春风满面、连续几届的全国政协委员,政协常委,在中国政商两界有着广泛的人脉。民间四传当年他的电话可以直通习办,高官们常常去他的豪宅喝茶打牌。传言也许有点夸张,但社交网络流传的众多视频和图片显示,许家印鼎盛期,“排场极大”,“恒大集团2017年年度工作会议”的场面,被指“看看全国人大会议怎么开就知道”,恒大集团主席许家印坐正中做报告,背后左右两翼,更像全国人大会议的“主席团”,台下是恒大集团的所有大小头目,个个仔细聆听。许家印“一览众山小”,意气风发的程度从其内部报纸可窥一斑。『恒大报』2017年9月26日头版如此标题:“许家印主席考察江苏会见省委书记省长达成进一步深化合作扩大投资共识”……许家印雄心勃勃,不仅搞房产,还花了数十亿元搞排球和足球,其领域甚至涵盖电动汽车。不过,民营企业首领,雄心再大,也得处处表白自己是 “党的人”,据中国媒体报道,恒大集团党委是广州市第一家民营企业党委,该集团共拥有35个党委18个党总支、1023个党支部、10841名党员。许家印常常说他的恒大是“党的恒大”,2018年9月13日,许家印获得第十届“中华慈善奖”,他领奖时说“我和恒大的一切,都是党给的”。仅仅两年后,2020年9月,党给的恒大开始爆雷了。彭博报道说,现在,这位富豪已成为习近平主席打击房地产行业过度杠杆和投机行为的最引人注目的牺牲品

    又爆大醜聞,總理李強很可能有個洋女婿