In order to use Letsencrypt SSL in MUP I just use add a proxy in the config file:
proxy: {
domains: 'mydomain.com,www.mudomain.com',
ssl: {
// Enable let's encrypt to create free certificates.
// The email is used by Let's Encrypt to notify you when the
// certificates are close to expiring.
letsEncryptEmail: 'user#candidsky.com'
// forceSSL: true
}
},
The documentation is here
http://meteor-up.com/docs.html#ssl-support
But I can't find anything on how to use a custom SSL, I need to use comodo SSL.
Here is a way to do it
app: {
...
ssl: {
crt: './bundle.crt', // this is a bundle of certificates
key: './private.key', // this is the private key of the certificate
port: 443 // 443 is the default value and it's the standard HTTPS port
}
...
}
Note that you also can set pem key in the key field.
http://meteor-up.com/docs.html#ssl-support
Related
I try to build an application with a GraphQL backend (based on Node.js and graphql-yoga). The server is hosted on a Linux machine with nginx as a reverse proxy. The proxy configuration is listed below.
server {
listen 443 ssl;
listen [::]:443 ssl;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
server_name url.example.com;
charset utf-8;
# Always serve index.html for any request
location / {
root /srv/app/public;
try_files $uri /index.html;
}
location /graphql {
allow all;
proxy_pass http://localhost:3000$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /playground {
# Additional configuration
}
location /subscriptions {
# Additional configuration
}
error_log /var/log/nginx/vue-app-error.log;
access_log /var/log/nginx/vue-app-access.log;
}
server {
listen 80;
listen [::]:80;
server_name url.example.com;
return 302 https://$server_name$request_uri;
To avoid CORS problems, I had to add the following entry in my servers configuration and it works.
const options = {
[
...
]
/**
* Cross-Origin Resource Sharing (CORS)
*/
cors: {
credentials: true,
origin: ['http://localhost:8080', 'https://url.example.com'], // frontend url
},
};
The authentication is based on JWT tokens packed into http-only cookies for access and refresh tokens. This is working as expected when I access my server with a browser and the cookies are shown in the developer tools. Within the AuthData, I additionally provide the username and a JWT token as a return value.
{
"data":{
"login":{
"user":"admin",
"name":" Admin",
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJhZG1pbiIsIm5hbWUiOiIgQWRtaW5pc3RyYXRvciIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5jb20iLCJpYXQiOjE2NDg0ODM2MDcsImV4cCI6MTY0ODQ4NzIwN30.Dol41LStkscXrlGn3GJotf83k_d2EImyvDU68Dg8Bvw"
}
},
"loading":false,
"networkStatus":7
}
Now I wanted to play around with Electron, because some use cases of the application would be much easier. The stack is Vue.js and Electron with Tailwind and the Apollo client (I use the Apollo UploadClient here) as listed below.
import {
ApolloClient,
ApolloLink,
DefaultOptions,
InMemoryCache,
} from '#apollo/client/core';
import { setContext } from '#apollo/client/link/context';
import { createUploadLink } from 'apollo-upload-client';
const backendServer = 'https://url.example.com/graphql';
const httpLink = createUploadLink({
uri: backendServer,
credentials: 'include',
});
// Cache implementation
const cache = new InMemoryCache({
addTypename: false,
}); //
const defaultOptions = {
watchQuery: {
fetchPolicy: 'no-cache',
},
query: {
fetchPolicy: 'no-cache',
errorPolicy: 'all',
},
mutate: {
errorPolicy: 'all',
},
} as DefaultOptions;
const authLink = setContext((_, { headers }) => ({
headers: {
...headers,
/**
* use a custom header tag to classify the application
* for authentication handling in the backend
*/
'app-type': 'web',
},
}));
const apolloClient = new ApolloClient({
link: ApolloLink.from([authLink, httpLink]),
cache,
defaultOptions,
resolvers: {},
});
export default apolloClient;
This client is bound to my Vue.js instance via #vue/apollo-composable. So I think it is only available in the renderer process. React examples I found on the Internet were built the same way.
Now the problem: When I run server and client (Electron) application on my development machine, everything works as expected, and I can see the cookies in the application tab in the developer tools. I also can access the API without issues.
When I now bind my ApolloClient to the remote API server I do not receive any cookies. From the logs I can see that I receive the AuthData like above from the server, but not the cookies. So any further request results in a custom error message "unauthenticated access" provided by my API server.
{
"loading":false,
"networkStatus":8,
"error":{
"graphQLErrors":[
{
"message":"user is not authenticated...redirect to the login page",
"locations":[
{"line":2,"column":3}
],
"path":[
"users"
]
}
],
"clientErrors":[],
"networkError":null,
"message":"user is not authenticated...redirect to the login page"
},"errors":[
{
"message":"user is not authenticated...redirect to the login page",
"locations":[
{"line":2,"column":3}
],
"path":[
"users"
]
}
]
}
What am I missing or doing wrong, or what else could I test?
Additional tested direct access
I additionally tested direct accessing the gql API from the electron client without the nginx proxy but still no success. I get the login correctly but I'm not able to see the cookies provided by the server.
any suggestions?
I am currently trying to build an API for a client interface-server interaction. I have decided to use ASP.NET Core for the API with Nginx as the hosting platform (On Ubuntu 18.04). Since ASP.NET uses Kestrel, we have set up a reverse proxy to forward requests from Nginx to Kestrel-- what is hosting the API. We have SSL set up on the NGINX server, however it is not set up on the Kestrel Server.
Simply put, I do not know how to set up SSL on the Kestrel Server with another layer of SSL on the NGINX side. How can I do this?
Model:
Client --> GET Request over HTTPS --> NGINX with SSL --> HTTP Kestrel Server and vice versa
Output: SSL_PROTOCOL_ERROR
Temporary Solution: Use HTTP with port 5000 in the link.-- No error, however, data is not secure.
Optimal Solution: Use HTTPS without port 5000 in the link. Data is secure.
NGINX Config:
if ($host = api.OURSITENAME.co) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name api.OURSITENAME.co;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
include /etc/nginx/proxy_params;
server_name api.OURSITENAME.co;
access_log /var/log/nginx/api.access.log;
error_log /var/log/nginx/api.error.log error;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/api.OURSITENAME.co/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.OURSITENAME.co/privkey.pem; # managed by Certbot
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
location / {
proxy_pass http://172.18.0.2:5000; <-- Docker Container. Can easily be switched out with localhost if we want to run on dotnet directly.
}
}
As I understand the problem, when you use HTTP to access your application directly on port 5000 you get an SSL error. Even though you don't use HTTPS.
If you have app.UseHsts(); and/or app.UseHttpsRedirection(); in your Startup code then it will use HTTPS.
If you are letting nginx handle the SSL then you can remove code from your app Startup.cs
Typical startup code:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else // Production
{
app.UseExceptionHandler("/Error");
// Remove to use HTTP only
app.UseHsts(); // HTTPS Strict mode
}
// Remove to use HTTP only
app.UseHttpsRedirection(); // Redirects HTTP to HTTPS
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc();
}
Documentation on enforcing SSL in dotnet core
This simply happens because Kestrel is not configured to handle HTTPS requests. A quick look at MS Docs shows you how.
You can use listenOptions and its various extensions to specify your SSL certificate and other configurations
webBuilder.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
// certificate is an X509Certificate2
listenOptions.ServerCertificate = certificate;
});
});
Also, if you used CreateDefaultBuilder from your Program.cs, then you can configure your SSL/HTTPS from appsettings.json because CreateDefaultBuilder calls Configure(context.Configuration.GetSection("Kestrel")) by default to load Kestrel configurations. A sample config file highlighting Kestrel config (from MS Docs) is shown below:
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
},
"HttpsInlineCertFile": {
"Url": "https://localhost:5001",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
},
"HttpsInlineCertStore": {
"Url": "https://localhost:5002",
"Certificate": {
"Subject": "<subject; required>",
"Store": "<certificate store; required>",
"Location": "<location; defaults to CurrentUser>",
"AllowInvalid": "<true or false; defaults to false>"
}
},
"HttpsDefaultCert": {
"Url": "https://localhost:5003"
},
"Https": {
"Url": "https://*:5004",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
},
"Certificates": {
"Default": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
}
}
Make sure to visit the docs if you need more info.
Nevertheless, in my opinion, I don't see much advantage with a double layer of SSL protection. One downside I can immediately notice is some delay as a result of encryption/decryption. A single layer of SSL on your reverse proxy should be more than enough.
I have a certificate, say, "./mysite.pfx" (that I've received from letsenctrypt). To enable HTTPS, I replaced
webBuilder.UseUrls("http://*:80");
with
webBuilder.UseUrls("http://*:80", "https://*:443");
But now if I visit the site it responds with MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT meaning that it cannot find the certificate file (I guess that's because dotnet sends a default). Where do I write the path to the file, how do I configure asp dot net project to use the ssl certificate and https protocol?
Windows 10, no IIS.
You can configure kestrel for your project in CreateHostBuilder method. Add SSL port listening (443 by default) and provide your certificate with password. Also do not forget to add redirection to https from http: Enforce HTTPS in ASP.NET Core
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel(options =>
{
options.Listen(IPAddress.Any, 80); // http
options.Listen(IPAddress.Any, 443, listenOptions => // https
{
listenOptions.UseHttps("certificate.pfx", "certificate-password");
});
});
webBuilder.UseStartup<Startup>();
// other stuff ...
}
I have a Meteor App based on Angular 1.3 + Meteor 1.5.2.2.
I am using Ubuntu 17.
I am trying to deploy my Meteor App on local machine first before going for live server using Meteor Up.
But I am facing this issue when running mup setup command
martinihenry#martinihenry:~/mytestapp-prod/.deploy$ mup setup
Started TaskList: Setup Docker
[192.168.100.12] - Setup Docker
events.js:141
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 192.168.100.12:22
at Object.exports._errnoException (util.js:907:11)
at exports._exceptionWithHostPort (util.js:930:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1078:14)
Here is my mup.json:
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '192.168.100.12',
username: 'root',
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
},
app: {
// TODO: change app name and path
name: 'mytestapp-prod',
path: '../',
servers: {
one: {},
},
buildOptions: {
serverOnly: true,
},
env: {
// TODO: Change to your app's url
// If you are using ssl, it needs to start with https://
ROOT_URL: '192.168.100.12:3000',
MONGO_URL: 'mongodb://localhost/meteor',
},
// ssl: { // (optional)
// // Enables let's encrypt (optional)
// autogenerate: {
// email: 'email.address#domain.com',
// // comma separated list of domains
// domains: 'website.com,www.website.com'
// }
// },
docker: {
// change to 'kadirahq/meteord' if your app is using Meteor 1.3 or older
image: 'abernix/meteord:base',
},
// Show progress bar while uploading bundle to server
// You might need to disable it on CI servers
enableUploadProgressBar: true
},
mongo: {
version: '3.4.1',
servers: {
one: {}
}
}
};
What could be wrong here?
It looks like you don't have sshd running on your machine, or you have not enabled remote ssh access for root.
You need to edit /etc/ssh/sshd_config, and comment out the following line:
PermitRootLogin without-password
Just below it, add the following line:
PermitRootLogin yes
Then restart SSH:
service ssh restart
I know this is late, but this a known and reproducable bug resulting from inotfiy-watch using all of the available slots for watches, and while very misleading, it actually has absolutely nothing to do with disk space.
The easy fix? increase watch slots:
sudo -i
echo 1048576 > /proc/sys/fs/inotify/max_user_watches
exit
The blog's URL is https://linuxhowto.tech/
It works great except specifically when I click on the title of my blog then the URL goes to http://localhost:2368/
I've looked at docs and config files and I'm not sure what would fix this. Any ideas? I'm about one inch from getting this blog to work and I'm sort of excited about it actually.
Addendum. I think adding my config.js might help.
// # Ghost Configuration
// Setup your Ghost install for various [environments](http://support.ghost.org/config/#about-environments).
// Ghost runs in `development` mode by default. Full documentation can be found at http://support.ghost.org/config/
var path = require('path'),
config;
config = {
// ### Production
// When running Ghost in the wild, use the production environment.
// Configure your URL and mail settings here
production: {
url: 'https://linuxhowto.tech',
mail: {},
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '/content/data/ghost.db')
},
debug: false
},
server: {
host: '127.0.0.1',
port: '2368'
}
},
// ### Development **(default)**
development: {
// The url to use when providing links to the site, E.g. in RSS and email.
// Change this to your Ghost blog's published URL.
url: 'https://linuxhowto.tech',
// Example refferer policy
// Visit https://www.w3.org/TR/referrer-policy/ for instructions
// default 'origin-when-cross-origin',
// referrerPolicy: 'origin-when-cross-origin',
// Example mail config
// Visit http://support.ghost.org/mail for instructions
// ```
// mail: {
// transport: 'SMTP',
// options: {
// service: 'Mailgun',
// auth: {
// user: '', // mailgun username
// pass: '' // mailgun password
// }
// }
// },
// ```
// #### Database
// Ghost supports sqlite3 (default), MySQL & PostgreSQL
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '/content/data/ghost-dev.db')
},
debug: false
},
// #### Server
// Can be host & port (default), or socket
server: {
// Host to be passed to node's `net.Server#listen()`
host: '127.0.0.1',
// Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
port: '2368'
},
// #### Paths
// Specify where your content directory lives
paths: {
contentPath: path.join(__dirname, '/content/')
}
},
// **Developers only need to edit below here**
// ### Testing
// Used when developing Ghost to run tests and check the health of Ghost
// Uses a different port number
testing: {
url: 'https://linuxhowto.tech',
database: {
client: 'sqlite3',
connection: {
filename: path.join(__dirname, '/content/data/ghost-test.db')
},
pool: {
afterCreate: function (conn, done) {
conn.run('PRAGMA synchronous=OFF;' +
'PRAGMA journal_mode=MEMORY;' +
'PRAGMA locking_mode=EXCLUSIVE;' +
'BEGIN EXCLUSIVE; COMMIT;', done);
}
},
useNullAsDefault: true
},
server: {
host: '127.0.0.1',
port: '2369'
},
logging: false
},
// ### Testing MySQL
// Used by Travis - Automated testing run through GitHub
'testing-mysql': {
url: 'https://linuxhowto.tech',
database: {
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'root',
password : '',
database : 'ghost_testing',
charset : 'utf8'
}
},
server: {
host: '127.0.0.1',
port: '2369'
},
logging: false
},
// ### Testing pg
// Used by Travis - Automated testing run through GitHub
'testing-pg': {
url: 'https://linuxhowto.tech',
database: {
client: 'pg',
connection: {
host : '127.0.0.1',
user : 'postgres',
password : '',
database : 'ghost_testing',
charset : 'utf8'
}
},
server: {
host: '127.0.0.1',
port: '2369'
},
logging: false
}
};
module.exports = config;
If you're self hosting this is accomplished by editing the url-field in the config.js file.
From the user docs:
One of the first things you’ll need to do after installing a Ghost blog, is set the URL for your blog in config.js. This URL must match the URL you will use to access your blog, if it is not set correctly you may get the error Access Denied from url as well as finding that RSS and other external links do not work correctly.
url should be set to the full URL for your blog including http:// or if you are using SSL for your blog and want both the admin and frontend to always be served securely, use https://. See the section on SSL configuration for more information about how to configure your URL if you want to use SSL for just the admin or only for secure requests.
If you want to Ghost to appear on a subpath or subdirectory of your domain, e.g. http://my-ghost-blog.com/blog/ the full path needs to be specified in the url field. This option is only available when self-hosting Ghost.
If you're using the Ghost Pro service I would suggest to contact their support.