locked
Website works if I connect through IP, not through domain (Apache) RRS feed

  • Question

  • User1148966005 posted

    I have an application that can be accessed using ip:5000, but not example.com/Panel. I'm trying to have the connection handled by Apache so I can tunnel HTTPS, but if I try to connect via example.com:5000, I get connection refused error. example.com/Panel gives me 404.

    This is my Program.cs:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
    	Host.CreateDefaultBuilder(args)
    		.ConfigureWebHostDefaults(webBuilder => {
    			webBuilder.UseUrls("http://*:5000");
    			webBuilder.UseStartup<Startup>();
    	});

    Apache config:

    <IfModule mod_ssl.c>
    <VirtualHost *:80>
            ServerName example.com
            DocumentRoot /var/www/html
            ServerAdmin me@example.com
    
            RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
    
            RewriteEngine on
            RewriteCond %{SERVER_NAME} =example.com
            RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    </VirtualHost>
    
    <VirtualHost *:443>
            ServerName example.com
            DocumentRoot /var/www/html
            ServerAdmin me@example.com
    
            RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
    
            RewriteEngine On
            ErrorLog "/var/log/apache2/rewrite"
            LogLevel alert rewrite:trace6
    
            ProxyRequests Off
            ProxyVia Off
            ProxyPreserveHost On
    
            <Proxy *>
                    Require all granted
            </Proxy>
    
            ProxyPass /Panel http://localhost:5000/Panel
            ProxyPassReverse /Panel http://localhost:5000/Panel
    
            SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
            SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
            Include /etc/letsencrypt/options-ssl-apache.conf
    </VirtualHost>
    </IfModule>
    

    Startup.cs:

    public class Startup {
        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services) {
            services.AddDbContext<ApplicationDbContext>(options => {
                options.UseNpgsql("...");
            });
            // Identity
            services.AddDefaultIdentity<ApplicationUser>(options => {
                options.SignIn.RequireConfirmedAccount = true;
                options.User.RequireUniqueEmail = false;
            })
                .AddDefaultUI()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
            services.AddControllersWithViews();
            services.AddRazorPages()
                .AddRazorRuntimeCompilation();
    
            // Hangfire 
            services.AddScoped<Jobs>();
            services.AddHangfire(x => x.UsePostgreSqlStorage("..."));
            services.AddHangfireServer();
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            } else {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseStaticFiles();
    
            app.UseRouting();
    
            app.UseForwardedHeaders(new ForwardedHeadersOptions {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            });
    
            app.UseAuthentication();
            app.UseAuthorization();
    
            app.UsePathBase("/Panel");
    
            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
                endpoints.MapRazorPages();
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
    
            // Hangfire
            app.UseHangfireDashboard("/Jobs", new DashboardOptions {
                Authorization = new [] { new HangfireAuthorizationFilter()}
            });
            RecurringJob.AddOrUpdate(() => Jobs.UpdateUsers(), Cron.Daily);
        }
    }

    I can't figure this out. I found nothing related to this on the internet so I clearly missed something.

    Wednesday, February 5, 2020 6:45 AM

Answers

  • User1148966005 posted

    I found the problem. Basically I had to change my Apache config to this:

    ProxyPass /Panel http://localhost:5000/Panel
    ProxyPassReverse /Panel http://localhost:5000/Panel
    

    Also I added this to my Startup.cs (found on ASP.NET Core issues tracker):

    app.Use((context, next) => {
    	context.Request.PathBase = new PathString("/Panel");
    	return next.Invoke();
    });

    Now it works. I was confused at first because I tried this Apache config previously and it did nothing. Now I connected the dots and it seems this additional Startup.cs is also necessary for my setup to run properly.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 6, 2020 12:51 PM

All replies

  • User-474980206 posted

    Did you config DNS or localhosts with the domain name?

    Wednesday, February 5, 2020 3:11 PM
  • User-864166757 posted

    Looking like either DNS entry is missing or if entry is there, then it can be synchronization issue.

    Thursday, February 6, 2020 12:15 AM
  • User1148966005 posted

    I have done nothing of that nature. I'm not sure what you mean, too - I previously used Django to make a similar website and successfully installed other, similar software on my server. I never had this kind of error.

    Also, what do you mean by synchronization issue? Like I said, the website can be accessed if I connect with IP and port, which means (I think) it works if it skips Apache entirely.

    Thursday, February 6, 2020 7:06 AM
  • User302204515 posted

    Is it a public website or a private website? If this is a public website you should buy a domain and register that domain with your IP address in DNS, than anyone else will be able to visit your site use the domain name you purchased. This can typically be done by consulting your domain service provider or your host provider.

    If this is a private website, you should consult your system admin to add your domain to your internal DNS server.

    if you are just doing some local test, you can edit your host file in your local system to map the domain to your ip address. Host file is actually a local cache of DNS

    Thursday, February 6, 2020 9:06 AM
  • User1148966005 posted

    It is a public website that is accessed by over 200 users daily. There are no problems with connecting to https://example.com or it's subdomains. 

    This issue is strange to me because this is my second take at using ASP.NET application on this server and it is a second time I'm having this problem. Last time I just assumed I messed up something so deeply I decided to create an entirely new solution. I was cautious of every change related to Kestrel this time but it still happened. Such problem didn't even cross my mind when I tested the waters with Django. Other similar software that is currently running on the server also didn't require any configuration other than ProxyPass.

    Thursday, February 6, 2020 9:47 AM
  • User1148966005 posted

    I found the problem. Basically I had to change my Apache config to this:

    ProxyPass /Panel http://localhost:5000/Panel
    ProxyPassReverse /Panel http://localhost:5000/Panel
    

    Also I added this to my Startup.cs (found on ASP.NET Core issues tracker):

    app.Use((context, next) => {
    	context.Request.PathBase = new PathString("/Panel");
    	return next.Invoke();
    });

    Now it works. I was confused at first because I tried this Apache config previously and it did nothing. Now I connected the dots and it seems this additional Startup.cs is also necessary for my setup to run properly.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 6, 2020 12:51 PM