vault backup: 2026-04-16 23:51:17

This commit is contained in:
2026-04-16 23:51:17 +08:00
parent 30e3efed83
commit 1290388f9c

View File

@@ -16,4 +16,273 @@
- 域名(内网):`nos-gzdev.163nos.com`
## 文档
- S3:https://sa.nie.netease.com/console/webconsole/idc/
- S3:https://sa.nie.netease.com/console/webconsole/idc/
# 垃圾电脑服务
我现在想在局域网里的另一台Ubuntu电脑上部署Unreal Horde服务存储 缓存以及管理各个worker、节点信息本机性能强劲作为worker进行具体工作。
- 电脑ip10.219.36.57
- 用户名netease
- 密码123
官方文档UE5.5
- https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-in-unreal-engine?application_version=5.5
- Horde README.md https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Programs/Horde/README.md
- [**Deploying Horde**](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Programs/Horde/Docs/Deployment.md)
- - 有关 Horde 的架构和组件的信息,以及部署它们的最佳实践。
**受众:** IT、系统管理员、打算修改 Horde 的程序员。
- [**Configuring and Operating Horde**](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Programs/Horde/Docs/Config.md)
- - 描述如何设置和管理 Horde。
**受众:**构建/开发运营团队、管理员。
- [**Horde Internals**](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Programs/Horde/Docs/Internals.md)
- - 描述如何构建和修改 Horde 及其架构。
**受众:**希望扩展 Horde 的开发人员。
- 视频
- [Horde and Unreal Build Accelerator: Operating at Epic Scale](https://youtu.be/ZUlwqNbYWBQ?si=DgFvrvepK67v-iTi)
## 下载地址
- 官方下载地址
- 服务端:https://github.com/EpicGames/UnrealEngine/releases/download/5.5.0-release/UnrealHordeServer.msi
# 大致步骤
1. 使用docker部署服务。
2. 服务器配置。
1. 默认端口Http 13340、Http 2 13342。
1. 默认情况下Horde配置为使用端口5000通过未加密的HTTP提供数据。在默认情况下代理通过端口5002使用未加密的HTTP/2上的gRPC与Horde服务器通信。这些设置在服务器启动时显示在控制台上。
2. [相关配置](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-orientation-for-unreal-engine?application_version=5.5)
- [服务器配置](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-settings-for-unreal-engine?application_version=5.5#%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%AE%BE%E7%BD%AE)将配置该服务器与其他服务器的通信,定义静态参数等。它由与该服务器一同部署的 `Server.json` 文件驱动。
- [完整配置参数清单](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-settings-for-unreal-engine?application_version=5.5#%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%AE%BE%E7%BD%AE)
- [全局配置](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-schema-for-unreal-engine?application_version=5.5#globals)在部署后控制所有面向用户的元素,该配置存于名为 `Globals.json` 的文件中。设置好部署参数后,大多数配置都在此处完成。
3. [验证相关配置](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-authentication-tutorial-for-unreal-engine?application_version=5.5)
1. [[#OIDC身份验证]]
3. 代理机配置。详见 http://10.219.103.35:13340/docs/Landing.md
1. 配置文件位置:安装目录\Agent\Defaults\agent.json
2.
# 部署笔记
## 部署流程
- [Horde服务器](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/horde-server-for-unreal-engine?application_version=5.5)
# Perforce服务器
ssl:inner02-commit.perforce.nie.netease.com:1667
# OIDC
## Netease OIDC信息
| | |
| ------------- | ---------------------------------------------------------------- |
| client id | 4884b03e951711f0ad370242ac120002 |
| client secret | f2862b8c5ab24085ab0883d119b631604884b354951711f0ad370242ac120002 |
## OIDC 参考代码
```python
#coding:UTF-8
"""
Requirements:
1. Flask >= 0.10.1
2. requests
3. jwkest >= 1.1.7
Usage:
python oidc_code_demo.py -H {listen_address} -p {listen_port}
Help:
python oidc_code_demo.py -h
"""
import os
import uuid
from hashlib import md5
import datetime
from urllib import urlencode
import json
import requests
from flask import Flask, request, jsonify, session, redirect
from jwkest.jwk import SYMKey
from jwkest.jws import JWS
from jwkest.jwk import load_jwks_from_url
from jwkest.jws import NoSuitableSigningKeys
__revision__ = "0.01"
__author__ = "chenxs@corp.netease.com"
OIDC_CLIENT_ID = ""
OIDC_CLIENT_SECRET = ""
OIDC_PROVIDER = "https://login.netease.com/connect"
OIDC_AUTHORIZATION_SERVER = "https://login.netease.com/connect/authorize"
OIDC_TOKEN_ENDPOINT = "https://login.netease.com/connect/token"
OIDC_USERINFO_ENDPOINT = "https://login.netease.com/connect/userinfo"
OIDC_SCOPE = "openid nickname email fullname dep title empno"
OIDC_REDIRECT_URI = "https://127.0.0.1:5000/finish"
OIDC_JWKS_URI = "https://login.netease.com/connect/jwks"
OIDC_ALG = "HS256"
PYTHON_OIDC_DEMO = Flask(__name__)
@PYTHON_OIDC_DEMO.route("/", methods=['GET'])
def index():
"""index"""
if 'username' in session:
body = (
u"</br><h2>OpenID Connect 鐧诲綍鎴愬姛銆<E5A79B></h2></br>"
u"鎮ㄧ殑鐢ㄦ埛鍚嶆槸锛<EFBFBD>%s</br>"
u"鎮ㄧ殑鍏ㄥ悕鏄細%s</br>"
u"鎮ㄧ殑閭鏄細%s</br>"
u"鎮ㄧ殑鑱屼綅鏄細%s</br>"
u"鎮ㄧ殑閮ㄩ棬鏄細%s</br>"
u"鎮ㄧ殑宸ュ彿鏄細%s</br>") % (
session['username'], session.get('fullname', ''),
session.get('email', ''), session.get('title', ''),
session.get('dep', ''), session.get('empno', ''))
body += u"<a href='/login'>鎴虫垜閲嶆柊鐧诲綍</a>"
return body
else:
return u"<a href='/login'>鎴虫垜鐧诲綍</a>"
@PYTHON_OIDC_DEMO.route("/login", methods=['GET'])
def login():
"""AuthN Request"""
session.clear()
now = datetime.datetime.now().strftime("%s")
session['uid'] = uuid.uuid4().hex
session['state'] = session['uid']
session['nonce'] = md5(session['uid'] + now).hexdigest()
authn_request_params = {
'response_type': 'code',
'client_id': OIDC_CLIENT_ID,
'state': session['state'],
'nonce': session['nonce'],
'scope': OIDC_SCOPE,
'redirect_uri': OIDC_REDIRECT_URI,
#'prompt': 'login',
'display': 'touch',
}
redirect_url = "?".join([
OIDC_AUTHORIZATION_SERVER, urlencode(authn_request_params)])
return redirect(redirect_url)
def token_request(code):
"""2. Token Request"""
params = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': OIDC_REDIRECT_URI,
'client_id': OIDC_CLIENT_ID,
'client_secret': OIDC_CLIENT_SECRET,
}
_resp = requests.post(OIDC_TOKEN_ENDPOINT, data=params)
return json.loads(_resp.text)
def id_token_verify(id_token, nonce=None):
"""3. id token verify"""
now = int(datetime.datetime.now().strftime("%s"))
if OIDC_ALG == "HS256":
signed_keys = [SYMKey(key=OIDC_CLIENT_SECRET)]
else:
signed_keys = load_jwks_from_url(OIDC_JWKS_URI)
try:
plain_id_token = JWS().verify_compact(id_token, signed_keys)
except NoSuitableSigningKeys:
# logger the id_token please
return {'error': 'can not verify the id token'}
print "idtoken: %s" % plain_id_token
if nonce:
if (not plain_id_token.has_key('nonce')) or (
plain_id_token['nonce'] != nonce):
return {'error': 'id token nonce not correct'}
if plain_id_token['iss'] != OIDC_PROVIDER:
return {'error': 'id token iss not correct'}
if plain_id_token['aud'] != OIDC_CLIENT_ID:
return {'error': 'id token aud not correct'}
if now >= int(plain_id_token['exp']):
return {'error': 'id token expired'}
return {'id_token': plain_id_token}
@PYTHON_OIDC_DEMO.route("/finish", methods=['GET'])
def finish():
"""
1. AuthN Response
2. Token Request
3. id token verify
4. userinfo request
5. login user
"""
# 1. AuthN Response
try:
code = request.args.get('code')
if session['state']:
state = request.args.get('state')
if state != session['state']:
return u"闈炴硶璇锋眰"
except ValueError:
return u"闈炴硶璇锋眰"
# 2. Token Request
token = token_request(code)
print "token: %s" % token
if token.has_key('error'):
return u"鍑洪敊浜嗭細%s" % str(token)
# 3. id token verify
id_token_verified = id_token_verify(token['id_token'])
if id_token_verified.has_key('error'):
return id_token_verified['error']
else:
id_token = id_token_verified['id_token']
print "id_token: %s" % id_token
# 4. userinfo request
_req_session = requests.Session()
_req_session.headers.update({
"Authorization": "Bearer %s" % token['access_token']})
userinfo_req = _req_session.get(OIDC_USERINFO_ENDPOINT)
userinfo = json.loads(userinfo_req.text)
# login the user
session['username'] = userinfo['nickname']
session['email'] = userinfo['email']
session['title'] = userinfo.get('title', '')
session['empno'] = userinfo.get('empno', '')
session['dep'] = userinfo.get('dep', '')
session['fullname'] = userinfo.get('fullname', '')
return redirect("/")
if __name__ == "__main__":
import sys
import argparse
parser = argparse.ArgumentParser(
usage='%(prog)s [options]', version='%(prog)s ' + str(__revision__))
parser.add_argument(
'-H', '--host', dest='host', type=str,
help="Specify listening adress, default is 127.0.0.1")
parser.add_argument(
'-p', '--port', dest='port', type=int,
help="Specify listening port, default is 5000")
parser.add_argument(
'-c', '--client_id', dest='client_id', type=str,
help="oidc client_id is required.")
parser.add_argument(
'-s', '--client_secret', dest='client_secret', type=str,
help="oidc client_secret is required.")
args = parser.parse_args()
host = args.host or '127.0.0.1'
port = args.port or 5000
OIDC_REDIRECT_URI = "http://%s:%s/finish" % (host, port)
OIDC_CLIENT_ID = args.client_id
OIDC_CLIENT_SECRET = args.client_secret
if not OIDC_CLIENT_ID or not OIDC_CLIENT_SECRET:
parser.print_help()
parser.exit()
PYTHON_OIDC_DEMO.secret_key = "this is a random secret"
PYTHON_OIDC_DEMO.debug = True
PYTHON_OIDC_DEMO.run(host=host, port=port)
```