My suggestion would be the following:
function is_login_page() {
return in_array( $GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ) );
}
function wpse_make_blog_private() {
if ( ! is_user_logged_in() && ! is_admin() && ! is_login_page() ) {
global $wp_query;
$wp_query->set_404();
}
}
add_action( 'wp', 'wpse_make_blog_private' );
It will show a 404 on all pages but still allow you to login. Logged in users will see the site as normal.
On your request to show a completely broken site add the following code to functions.php. Be aware that this is instead of the code above.
function is_login_page() {
return in_array( $GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ) );
}
function wpse_make_blog_private() {
if ( ! is_user_logged_in() && ! is_admin() && ! is_login_page() ) {
die();
}
}
add_action( 'wp', 'wpse_make_blog_private' );
You have the option of using wp_die instead to add an error message with minimal styling. See: https://codex.wordpress.org/Function_Reference/wp_die