Sirve tu sitio y vende cursos con un servidor autohospedado.
sserver es un servidor simple y sin cabeza para alojar cursos y blogs/contenido estático asociado desde un repositorio privado de github con una sobrecarga mínima.
Proporciona https listo para usar para que no tenga que lidiar con la instalación/administración de certificados. Sincroniza el contenido automáticamente desde github para que no tengas que cargar tu contenido en el servidor. También admite contenido premium con un archivo de configuración simple sin afectar su flujo de trabajo de contenido; por ejemplo, si está utilizando un generador de sitios estáticos como hugo, puede ocultar el contenido premium al público especificándolo en el archivo de configuración. Tiene integración de banda para que puedas vender tu contenido premium. Tiene administración de usuarios incorporada para agregar/autenticar usuarios. También tiene una API de administración para que pueda monitorear los pedidos/usuarios de su sitio.
A continuación se muestran algunos ejemplos de cómo se puede utilizar. Asegúrese de configurar las variables de entorno SS_<> antes de probarlas, por ejemplo.
export SS_GITHUB_TOKEN=<github_token>
export SS_STRIPE_TOKEN=<stripe_token>
export SS_SMTP_FROM=<email_id>
export SS_SMTP_USER=<smtp_username>
export SS_SMTP_PWD=<smtp_password>
export SS_SMTP_HOST=<smtp_host_address>
export SS_SMTP_PORT=<smtp_port>
export SS_ADMIN_EMAIL=<admin_email>
export SS_ADMIN_PWD=<admin_password_for_sserver>
./sserver -repo "https://github.com/newbeelearn/sserver.git"
El repositorio debe tener index.html y ssconfig.toml en su directorio raíz. Si se utiliza hugo/jekyll, etc., como un generador de sitios estáticos, el repositorio debe contener el sitio generado (tendría index.html en la raíz de forma predeterminada).
./sserver -repo "https://github.com/newbeelearn/sserver.git?folder=public"
El repositorio debe tener index.html en la carpeta desde donde desea publicar el contenido; normalmente es público si se utilizan generadores de sitios estáticos de hugo/jekyll, etc. Debería tener ssconfig.toml en el directorio raíz.
./sserver -repo "https://github.com/newbeelearn/sserver.git?ref=test-config"
La rama debe tener index.html y ssconfig.toml en su directorio raíz. Si se utiliza hugo/jekyll, etc., como un generador de sitios estáticos, la rama debe contener el sitio generado (tendría index.html en la raíz de forma predeterminada).
./sserver -repo "https://github.com/newbeelearn/sserver.git?domain=example.com"
El repositorio debe tener index.html y ssconfig.toml en su directorio raíz. Acceso al dominio desde el cual se sirve el sitio. El servidor debe tener permisos para vincularse al puerto 443, esto se puede hacer con el siguiente comando.
sudo setcap 'cap_net_bind_service=+ep' sserver
./sserver -repo "file:///workspace/projects/newbeelearn.com/sserver"
El repositorio debe tener index.html y ssconfig.toml en su directorio raíz. Todas las opciones, es decir, carpeta/dominio, etc., también se pueden especificar en el caso de archivos locales.
A continuación se puede encontrar un ejemplo de ssconfig.toml
# specify the site
[site]
# period to check for new content
syncinterval = "@every 12h"
# product/course details
[[site.prod]]
name = "course1"
# path from root, this will be accessible to users who have bought the course
path = "courses/course1"
# can be draft/active, buying functionality will be enabled when status is active
status = "active"
# unique identifier for the course
sku = "prod-course-1"
# price in cents
price = 10000
# currency
currency = "USD"
sserver crea el directorio "wwwss" desde donde se ejecuta
drwxrwxr-x 2 test test 4096 Nov 30 17:04 a
drwxrwxr-x 8 test test 4096 Nov 30 17:04 b
drwxrwxr-x 2 test test 4096 Nov 30 17:04 certs
drwxrwxr-x 2 test test 4096 Nov 30 17:04 logs
-rw-rw-r-- 1 test test 527483 Nov 30 17:04 tmp.zip
-rw-rw-r-- 1 test test 49152 Nov 30 17:05 ssapp.db
El archivo de configuración se utiliza para especificar los productos/cursos que desea vender, así como algunos parámetros del servidor, como la frecuencia con la que se debe sincronizar el sitio, etc.
El archivo ssconfig.toml de muestra se muestra a continuación
#specify the site
[site]
#period to check for new content default is 12 hours
syncinterval = "@every 12h"
[[site.prod]]
name = "course1"
path = "courses/course1"
status = "active"
sku = "prod-course-1"
price = 10000
currency = "USD"
Todos los puntos finales de la API son relativos al dominio utilizado para servir el contenido, es decir, si el dominio es ejemplo.com y la API es /api/v1/product/list
la solicitud sería https://example.com/api/v1/product/list
La jerarquía de roles es así: administrador > usuario > invitado. Cualquier API a la que pueda acceder el invitado también lo es para el usuario y cualquier API a la que pueda acceder el usuario también lo es para el administrador. Para acceder a la sesión de la API del usuario/administrador, la cookie obtenida después de iniciar sesión se debe proporcionar con cada solicitud en Practique esto será atendido por el navegador.
Descripción | Pedido | Role |
---|---|---|
Registrar Usuario | POST /api/v1/user/register | invitado |
Iniciar sesión usuario | ENVIAR /api/v1/user/login | invitado |
Cerrar sesión de usuario | OBTENER /api/v1/user/logout | invitado |
Verificar usuario | OBTENER /api/v1/user/verify/:id | invitado |
Restablecer contraseña de usuario | ENVIAR /api/v1/user/reset | invitado |
Obtener lista de productos | OBTENER /api/v1/product/list | invitado |
Crear pedido | ENVIAR /api/v1/order/id | invitado |
Modificar orden | PUT /api/v1/order/id | usuario |
orden de pago | ENVIAR /api/v1/order/checkout | usuario |
Obtener pedido por ID de pedido | OBTENER /api/v1/order/id/:id | usuario |
Obtener todos los pedidos por usuario | OBTENER /api/v1/order/id/list | usuario |
Cambiar contraseña de usuario | POST /api/v1/user/changepwd | usuario |
Obtener todos los pedidos | OBTENER /api/v1/order/list | administración |
Obtener todos los usuarios | OBTENER /api/v1/user/list | administración |
Registrar nuevo usuario con correo electrónico y contraseña. Envía un correo al correo electrónico utilizado para registrarse con un código de verificación si está configurada la configuración del servidor SMTP.
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/register'
-H 'Content-Type: application/x-www-form-urlencoded'
-X POST
--data-raw 'email=stripe%40newbeelearn.com&password=test&confirm-password=test&remember=on'
Ejemplo de respuesta
{"status":"success"}
Usuario de inicio de sesión con correo electrónico y contraseña. Devuelve json si el campo "postlogin" no está configurado en el archivo de configuración; de lo contrario, redirige a la página especificada en "postlogin"
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/login'
-H 'Content-Type: application/x-www-form-urlencoded'
-X POST
--data-raw 'email=admin%40example.com&password=admin'
Ejemplo de respuesta
{
"data": {
"user_id": "1",
"username": ""
},
"msg": "user found",
"status": "success"
}
Cierra la sesión del usuario que inició sesión y redirige a la página de inicio
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/logout'
-H 'Cookie: session_id=9e8b22a3-15ac-442f-bf65-15c37dbfc889; max-age=300; path=/; secure; SameSite=Lax'
Ejemplo de respuesta
<!doctype html>
<html lang="en">
<head>
</head>
<body>
</body>
</html>
Verifica el correo electrónico del usuario registrado enviando la URL si el dominio está configurado o el código que debe agregarse después de la API de verificación si el dominio no está configurado
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/verify/cafj5grn0gpog1j3a0m0'
Ejemplo de respuesta
{"status":"success"}
Restablece la contraseña del usuario y envía el nuevo código temporal para iniciar sesión. El usuario debe utilizar este código en el próximo inicio de sesión y cambiar la contraseña.
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/reset'
-H 'Content-Type: application/x-www-form-urlencoded'
-X POST
--data-raw 'email=stripe%40newbeelearn.com'
Ejemplo de respuesta
{
"data": null,
"msg": "password reset successful",
"status": "success"
}
Obtenga todos los productos listados para la venta en el sitio web. Toma "límite" y "compensación" como consultas. Si la consulta no está configurada, los valores predeterminados del límite se establecen en 10 y se compensan en 0
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/product/list?limit=1&offset=0'
Ejemplo de respuesta
{
"data": [
{
"prd_id": 1,
"prd_name": "course1",
"sku": "prod-course-1",
"permalink": "users/list/",
"price": 10000,
"currency": "USD",
"period": 365,
"status": "active"
}
],
"msg": "Order found",
"status": "success"
}
Crea un nuevo pedido con los productos enumerados en el campo "line_item"
. La solicitud debe ser un json válido. Los campos reales order_id/user_id
etc. los completa el servidor y se puede pasar cualquier valor ficticio.
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/order/id'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=cad8439e-dcc4-475e-94fc-12b75f85bb20; max-age=300; path=/; secure; SameSite=Lax'
-X POST
--data-raw ' {
"order_id": 1,
"user_id": 3,
"currency": "USD",
"line_items": [
{
"sku": "prod-course-1"
},
{
"sku": "prod-course-3"
}
]
}'
Ejemplo de respuesta
{
"data": {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 11000,
"line_items": [
{
"line_id": 1,
"order_id": 1,
"prd_id": 1,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 10000,
"enabled": true,
"sku": "prod-course-1"
},
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
},
"msg": "Order found",
"status": "success"
}
Modifica el pedido existente agregando/eliminando productos en el campo line_item
. El usuario debe iniciar sesión para modificar el pedido y el pedido debe estar en estado activo. Utilice la respuesta anterior de crear pedido u obtener pedido para agregar/eliminar productos
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/order/id'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=cad8439e-dcc4-475e-94fc-12b75f85bb20; max-age=300; path=/; secure; SameSite=Lax'
-X PUT
--data-raw ' {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 11000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
}'
Ejemplo de respuesta
{
"data": {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 1000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
},
"msg": "Order found",
"status": "success"
}
Obtiene la URL de banda para el pago del pedido creado mediante la API de creación de pedidos. Utilice la respuesta de crear pedido/modificar pedido/obtener API de pedido para enviar la solicitud. No modifique la respuesta en esta solicitud, ya que resultará en un error.
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/order/checkout'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=2f1be070-7256-4e84-a4ef-c14754cabcdb; max-age=300; path=/; secure; SameSite=Lax'
-X POST
--data-raw ' {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 11000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
}'
Ejemplo de respuesta
{
"data": {
"url": "https://checkout.stripe.com/pay/cs_test_a17D2l74NsKMv29YJ1c5rSBPx7BGSsNAsObGAsOanEJqyFNXKEYDLji4BZ#fidkdWxOYHwnPyd1blpxYHZxWjA0TlVKPHNMaW9vYEd1YmhdUWQ3UUJqSEpMYTMza11ObGAyXDFPcXA8bz1yY1VicVZVdDN8c1NkaUZEazxIQWdjM04wdz1DTmF3PXxHaVE9bTVuZz1pUWw3NTUybHZLZldgaicpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl"
},
"msg": "Order found",
"status": "success"
}
Obtenga detalles del pedido por número de pedido
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/order/id/cafjktbn0gpp5hq3dt4g'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=fe9b9fff-c5c0-4745-becf-ecb0e5abca81; max-age=300; path=/; secure; SameSite=Lax'
Ejemplo de respuesta
{
"data": {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 1000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"grand": 1000,
"enabled": true
}
]
},
"msg": "Order found",
"status": "success"
}
Obtenga todos los pedidos por usuario. Toma límite y desplazamiento como parámetros de consulta, los valores predeterminados son 10 y 0 respectivamente
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/order/id/list?limit=1&offset=0'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=fe9b9fff-c5c0-4745-becf-ecb0e5abca81; max-age=300; path=/; secure; SameSite=Lax'
Ejemplo de respuesta
{
"data": [
{
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 1000
}
],
"msg": "Order found",
"status": "success"
}
Cambiar contraseña de usuario. El usuario debe iniciar sesión para realizar esta solicitud.
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/changepwd'
-H 'Content-Type: application/x-www-form-urlencoded'
-H 'Cookie: session_id=fe9b9fff-c5c0-4745-becf-ecb0e5abca81; max-age=300; path=/; secure; SameSite=Lax'
-X POST
--data-raw 'oldpassword=cafjjjbn0gpp5hq3dt40&password=test123'
Ejemplo de respuesta
{
"data": null,
"msg": "password change successful",
"status": "success"
}
Obtén todos los pedidos creados en la tienda. Toma límite y desplazamiento como parámetros de consulta. Los valores predeterminados son 10 y 0 respectivamente. Disponible solo para usuarios administradores. Obtener todos los pedidos
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/order/list?limit=1&offset=0'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=e4ecd3a4-b8be-493e-a33d-518ab11c65e8; max-age=300; path=/; secure; SameSite=Lax'
Ejemplo de respuesta
{
"data": [
{
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"price_total": 1000,
"discount_total": 0,
"sub_total": 1000,
"taxes_total": 0,
"grand_total": 1000,
"refunds_total": 0,
"created_channel": "",
"payment_provider": ""
}
],
"msg": "Order found",
"status": "success"
}
Obtener todos los usuarios registrados en el sitio web. Toma límite y desplazamiento como parámetros de consulta. Los valores predeterminados son 10 y 0 respectivamente. Disponible solo para usuarios administradores.
Solicitud de ejemplo
curl 'http://localhost:54545/api/v1/user/list?limit=1&offset=0'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=e4ecd3a4-b8be-493e-a33d-518ab11c65e8; max-age=300; path=/; secure; SameSite=Lax'
Ejemplo de respuesta
{
"data": [
{
"user_id": 1,
"email": "[email protected]",
"created_at": "2022-06-07 10:53:00.480128762 +0000 UTC",
"username": "",
"last_password_set": "2022-06-07 10:53:00.480128762 +0000 UTC",
"last_login": "2022-06-07 10:53:00.480128762 +0000 UTC",
"verified": 0,
"reset": 0,
"user_role": "admin"
},
{
"user_id": 2,
"email": "[email protected]",
"created_at": "2022-06-07 10:53:00.532691788 +0000 UTC",
"username": "",
"last_password_set": "2022-06-07 10:53:00.532691788 +0000 UTC",
"last_login": "2022-06-07 10:53:00.532691788 +0000 UTC",
"verified": 0,
"reset": 0,
"user_role": "guest"
},
{
"user_id": 3,
"email": "[email protected]",
"created_at": "2022-06-07 11:13:06.947313364 +0000 UTC",
"username": "",
"last_password_set": "2022-06-07 11:13:06.947313364 +0000 UTC",
"last_login": "2022-06-07 11:13:06.947313364 +0000 UTC",
"verified": 2,
"reset": 1,
"user_role": "user"
}
],
"msg": "Order found",
"status": "success"
}
No, sólo se publican archivos binarios y el sitio se utiliza para debates sobre el producto.
Su funcionalidad en etapa alfa está completa, sin embargo, puede contener errores.
Esto fue creado debido a la necesidad de albergar cursos.
En este momento no porque la suscripción no es compatible; es solo para productos digitales por única vez. Tampoco tiene una funcionalidad de reenvío de rutas donde se puede conectar su propio saas. Sin embargo, estos cambios se pueden agregar si hay suficiente interés. Inicie la discusión si desea tener estas características a partir de ahora, no están en la hoja de ruta.
Se puede utilizar para alojar cursos y blogs asociados. Blogs con newsletter. Blogs con contenido premium. Landing page de la startup y blog asociado. Vender temas, etc.
Linux y Macos son compatibles desde el primer momento. Los usuarios de Windows pueden utilizar WSL, aunque no está probado.
Crear problema y etiquetarlo con característica
Esto aún no está decidido; por ahora, su uso es gratuito. El producto pago, si está disponible, utilizará un canal separado. Entonces, si lo descarga desde la versión github, será gratis para siempre. Ayúdanos a decidirlo, cuéntanos cuánto pagarías por ello en el foro de discusión.